aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/nextpnr.cc9
-rw-r--r--ecp5/arch.cc105
-rw-r--r--ecp5/arch.h92
-rw-r--r--ecp5/arch_pybindings.h18
-rw-r--r--ecp5/bitstream.cc5
-rw-r--r--gui/designwidget.cc26
-rw-r--r--ice40/arch.h1
-rwxr-xr-xice40/picorv32.sh8
8 files changed, 129 insertions, 135 deletions
diff --git a/common/nextpnr.cc b/common/nextpnr.cc
index 01c1397e..33230db0 100644
--- a/common/nextpnr.cc
+++ b/common/nextpnr.cc
@@ -170,21 +170,20 @@ uint32_t Context::checksum() const
void Context::check() const
{
- auto &&proxy = rproxy();
for (auto &n : nets) {
auto ni = n.second.get();
NPNR_ASSERT(n.first == ni->name);
for (auto &w : ni->wires) {
- NPNR_ASSERT(n.first == proxy.getBoundWireNet(w.first));
+ NPNR_ASSERT(n.first == getBoundWireNet(w.first));
if (w.second.pip != PipId()) {
NPNR_ASSERT(w.first == getPipDstWire(w.second.pip));
- NPNR_ASSERT(n.first == proxy.getBoundPipNet(w.second.pip));
+ NPNR_ASSERT(n.first == getBoundPipNet(w.second.pip));
}
}
}
for (auto w : getWires()) {
- IdString net = proxy.getBoundWireNet(w);
+ IdString net = getBoundWireNet(w);
if (net != IdString()) {
NPNR_ASSERT(nets.at(net)->wires.count(w));
}
@@ -193,7 +192,7 @@ void Context::check() const
for (auto &c : cells) {
NPNR_ASSERT(c.first == c.second->name);
if (c.second->bel != BelId())
- NPNR_ASSERT(proxy.getBoundBelCell(c.second->bel) == c.first);
+ NPNR_ASSERT(getBoundBelCell(c.second->bel) == c.first);
for (auto &port : c.second->ports) {
NetInfo *net = port.second.net;
if (net != nullptr) {
diff --git a/ecp5/arch.cc b/ecp5/arch.cc
index 5c5689f0..51f4db84 100644
--- a/ecp5/arch.cc
+++ b/ecp5/arch.cc
@@ -151,7 +151,7 @@ IdString Arch::archArgsToId(ArchArgs args) const
// -----------------------------------------------------------------------
-BelId ArchReadMethods::getBelByName(IdString name) const
+BelId Arch::getBelByName(IdString name) const
{
BelId ret;
auto it = bel_by_name.find(name);
@@ -160,9 +160,9 @@ BelId ArchReadMethods::getBelByName(IdString name) const
Location loc;
std::string basename;
- std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(parent_));
+ std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
ret.location = loc;
- const LocationTypePOD *loci = parent_->locInfo(ret);
+ const LocationTypePOD *loci = locInfo(ret);
for (int i = 0; i < loci->num_bels; i++) {
if (std::strcmp(loci->bel_data[i].name.get(), basename.c_str()) == 0) {
ret.index = i;
@@ -185,14 +185,14 @@ BelRange Arch::getBelsAtSameTile(BelId bel) const
return br;
}
-WireId ArchReadMethods::getWireBelPin(BelId bel, PortPin pin) const
+WireId Arch::getWireBelPin(BelId bel, PortPin pin) const
{
WireId ret;
NPNR_ASSERT(bel != BelId());
- int num_bel_wires = parent_->locInfo(bel)->bel_data[bel.index].num_bel_wires;
- const BelWirePOD *bel_wires = parent_->locInfo(bel)->bel_data[bel.index].bel_wires.get();
+ int num_bel_wires = locInfo(bel)->bel_data[bel.index].num_bel_wires;
+ const BelWirePOD *bel_wires = locInfo(bel)->bel_data[bel.index].bel_wires.get();
for (int i = 0; i < num_bel_wires; i++)
if (bel_wires[i].port == pin) {
ret.location = bel.location + bel_wires[i].rel_wire_loc;
@@ -205,7 +205,7 @@ WireId ArchReadMethods::getWireBelPin(BelId bel, PortPin pin) const
// -----------------------------------------------------------------------
-WireId ArchReadMethods::getWireByName(IdString name) const
+WireId Arch::getWireByName(IdString name) const
{
WireId ret;
auto it = wire_by_name.find(name);
@@ -214,9 +214,9 @@ WireId ArchReadMethods::getWireByName(IdString name) const
Location loc;
std::string basename;
- std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(parent_));
+ std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
ret.location = loc;
- const LocationTypePOD *loci = parent_->locInfo(ret);
+ const LocationTypePOD *loci = locInfo(ret);
for (int i = 0; i < loci->num_wires; i++) {
if (std::strcmp(loci->wire_data[i].name.get(), basename.c_str()) == 0) {
ret.index = i;
@@ -233,7 +233,7 @@ WireId ArchReadMethods::getWireByName(IdString name) const
// -----------------------------------------------------------------------
-PipId ArchReadMethods::getPipByName(IdString name) const
+PipId Arch::getPipByName(IdString name) const
{
auto it = pip_by_name.find(name);
if (it != pip_by_name.end())
@@ -242,13 +242,13 @@ PipId ArchReadMethods::getPipByName(IdString name) const
PipId ret;
Location loc;
std::string basename;
- std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(parent_));
- const LocationTypePOD *loci = parent_->locInfo(ret);
+ std::tie(loc.x, loc.y, basename) = split_identifier_name(name.str(this));
+ const LocationTypePOD *loci = locInfo(ret);
for (int i = 0; i < loci->num_pips; i++) {
PipId curr;
curr.location = loc;
curr.index = i;
- pip_by_name[parent_->getPipName(curr)] = curr;
+ pip_by_name[getPipName(curr)] = curr;
}
return pip_by_name[name];
}
@@ -296,7 +296,7 @@ bool Arch::route() { return router1(getCtx()); }
// -----------------------------------------------------------------------
-std::vector<GraphicElement> ArchReadMethods::getDecalGraphics(DecalId decalId) const
+std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decalId) const
{
std::vector<GraphicElement> ret;
// FIXME
@@ -315,9 +315,9 @@ DecalXY Arch::getGroupDecal(GroupId pip) const { return {}; };
// -----------------------------------------------------------------------
-bool ArchReadMethods::isValidBelForCell(CellInfo *cell, BelId bel) const { return true; }
+bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const { return true; }
-bool ArchReadMethods::isBelLocationValid(BelId bel) const { return true; }
+bool Arch::isBelLocationValid(BelId bel) const { return true; }
// -----------------------------------------------------------------------
@@ -330,77 +330,4 @@ IdString Arch::getPortClock(const CellInfo *cell, IdString port) const { return
bool Arch::isClockPort(const CellInfo *cell, IdString port) const { return false; }
-bool ArchReadMethods::checkWireAvail(WireId wire) const
-{
- NPNR_ASSERT(wire != WireId());
- return wire_to_net.find(wire) == wire_to_net.end() || wire_to_net.at(wire) == IdString();
-}
-
-bool ArchReadMethods::checkPipAvail(PipId pip) const
-{
- NPNR_ASSERT(pip != PipId());
- return pip_to_net.find(pip) == pip_to_net.end() || pip_to_net.at(pip) == IdString();
-}
-
-bool ArchReadMethods::checkBelAvail(BelId bel) const
-{
- NPNR_ASSERT(bel != BelId());
- return bel_to_cell.find(bel) == bel_to_cell.end() || bel_to_cell.at(bel) == IdString();
-}
-
-IdString ArchReadMethods::getConflictingBelCell(BelId bel) const
-{
- NPNR_ASSERT(bel != BelId());
- if (bel_to_cell.find(bel) == bel_to_cell.end())
- return IdString();
- else
- return bel_to_cell.at(bel);
-}
-
-IdString ArchReadMethods::getConflictingWireNet(WireId wire) const
-{
- NPNR_ASSERT(wire != WireId());
- if (wire_to_net.find(wire) == wire_to_net.end())
- return IdString();
- else
- return wire_to_net.at(wire);
-}
-
-IdString ArchReadMethods::getConflictingPipNet(PipId pip) const
-{
- NPNR_ASSERT(pip != PipId());
- if (pip_to_net.find(pip) == pip_to_net.end())
- return IdString();
- else
- return pip_to_net.at(pip);
-}
-
-IdString ArchReadMethods::getBoundWireNet(WireId wire) const
-{
- NPNR_ASSERT(wire != WireId());
- if (wire_to_net.find(wire) == wire_to_net.end())
- return IdString();
- else
- return wire_to_net.at(wire);
-}
-
-IdString ArchReadMethods::getBoundPipNet(PipId pip) const
-{
- NPNR_ASSERT(pip != PipId());
- if (pip_to_net.find(pip) == pip_to_net.end())
- return IdString();
- else
- return pip_to_net.at(pip);
-}
-
-IdString ArchReadMethods::getBoundBelCell(BelId bel) const
-{
- NPNR_ASSERT(bel != BelId());
- if (bel_to_cell.find(bel) == bel_to_cell.end())
- return IdString();
- else
- return bel_to_cell.at(bel);
-}
-
-
NEXTPNR_NAMESPACE_END
diff --git a/ecp5/arch.h b/ecp5/arch.h
index 50897b86..421a7738 100644
--- a/ecp5/arch.h
+++ b/ecp5/arch.h
@@ -371,6 +371,8 @@ public:
// -------------------------------------------------
+ BelId getBelByName(IdString name) const;
+
template <typename Id> const LocationTypePOD *locInfo(Id &id) const
{
return &(chip_info->locations[chip_info->location_type[id.location.y * chip_info->width + id.location.x]]);
@@ -404,6 +406,30 @@ public:
bel_to_cell[bel] = IdString();
}
+ bool checkBelAvail(BelId bel) const
+ {
+ NPNR_ASSERT(bel != BelId());
+ return bel_to_cell.find(bel) == bel_to_cell.end() || bel_to_cell.at(bel) == IdString();
+ }
+
+ IdString getBoundBelCell(BelId bel) const
+ {
+ NPNR_ASSERT(bel != BelId());
+ if (bel_to_cell.find(bel) == bel_to_cell.end())
+ return IdString();
+ else
+ return bel_to_cell.at(bel);
+ }
+
+ IdString getConflictingBelCell(BelId bel) const
+ {
+ NPNR_ASSERT(bel != BelId());
+ if (bel_to_cell.find(bel) == bel_to_cell.end())
+ return IdString();
+ else
+ return bel_to_cell.at(bel);
+ }
+
BelRange getBels() const
{
BelRange range;
@@ -439,6 +465,8 @@ public:
return locInfo(bel)->bel_data[bel.index].type;
}
+ WireId getWireBelPin(BelId bel, PortPin pin) const;
+
BelPin getBelPinUphill(WireId wire) const
{
BelPin ret;
@@ -466,6 +494,8 @@ public:
// -------------------------------------------------
+ WireId getWireByName(IdString name) const;
+
IdString getWireName(WireId wire) const
{
NPNR_ASSERT(wire != WireId());
@@ -505,6 +535,30 @@ public:
wire_to_net[wire] = IdString();
}
+ bool checkWireAvail(WireId wire) const
+ {
+ NPNR_ASSERT(wire != WireId());
+ return wire_to_net.find(wire) == wire_to_net.end() || wire_to_net.at(wire) == IdString();
+ }
+
+ IdString getBoundWireNet(WireId wire) const
+ {
+ NPNR_ASSERT(wire != WireId());
+ if (wire_to_net.find(wire) == wire_to_net.end())
+ return IdString();
+ else
+ return wire_to_net.at(wire);
+ }
+
+ IdString getConflictingWireNet(WireId wire) const
+ {
+ NPNR_ASSERT(wire != WireId());
+ if (wire_to_net.find(wire) == wire_to_net.end())
+ return IdString();
+ else
+ return wire_to_net.at(wire);
+ }
+
WireRange getWires() const
{
WireRange range;
@@ -520,6 +574,7 @@ public:
// -------------------------------------------------
+ PipId getPipByName(IdString name) const;
IdString getPipName(PipId pip) const;
uint32_t getPipChecksum(PipId pip) const { return pip.index; }
@@ -555,6 +610,30 @@ public:
pip_to_net[pip] = IdString();
}
+ bool checkPipAvail(PipId pip) const
+ {
+ NPNR_ASSERT(pip != PipId());
+ return pip_to_net.find(pip) == pip_to_net.end() || pip_to_net.at(pip) == IdString();
+ }
+
+ IdString getBoundPipNet(PipId pip) const
+ {
+ NPNR_ASSERT(pip != PipId());
+ if (pip_to_net.find(pip) == pip_to_net.end())
+ return IdString();
+ else
+ return pip_to_net.at(pip);
+ }
+
+ IdString getConflictingPipNet(PipId pip) const
+ {
+ NPNR_ASSERT(pip != PipId());
+ if (pip_to_net.find(pip) == pip_to_net.end())
+ return IdString();
+ else
+ return pip_to_net.at(pip);
+ }
+
AllPipRange getPips() const
{
AllPipRange range;
@@ -637,7 +716,6 @@ public:
// -------------------------------------------------
- // TODO(q3k) move this to archproxies?
GroupId getGroupByName(IdString name) const { return GroupId(); }
IdString getGroupName(GroupId group) const { return IdString(); }
std::vector<GroupId> getGroups() const { return std::vector<GroupId>(); }
@@ -648,8 +726,6 @@ public:
// -------------------------------------------------
- // These are also specific to the chip and not state, so they're available
- // on arch directly.
void estimatePosition(BelId bel, int &x, int &y, bool &gb) const;
delay_t estimateDelay(WireId src, WireId dst) const;
delay_t getDelayEpsilon() const { return 20; }
@@ -665,7 +741,8 @@ public:
// -------------------------------------------------
- // TODO(q3k) move this to archproxies?
+ std::vector<GraphicElement> getDecalGraphics(DecalId decal) const;
+
DecalXY getFrameDecal() const;
DecalXY getBelDecal(BelId bel) const;
DecalXY getWireDecal(WireId wire) const;
@@ -683,6 +760,11 @@ public:
bool isClockPort(const CellInfo *cell, IdString port) const;
// Return true if a port is a net
bool isGlobalNet(const NetInfo *net) const;
+
+ // -------------------------------------------------
+ // Placement validity checks
+ bool isValidBelForCell(CellInfo *cell, BelId bel) const;
+ bool isBelLocationValid(BelId bel) const;
};
class ArchReadMethods : public BaseReadCtx
@@ -718,6 +800,8 @@ class ArchReadMethods : public BaseReadCtx
bool isValidBelForCell(CellInfo *cell, BelId bel) const;
// Return true whether all Bels at a given location are valid
bool isBelLocationValid(BelId bel) const;
+ // Helper function for above
+ bool logicCellsCompatible(const std::vector<const CellInfo *> &cells) const;
bool checkWireAvail(WireId wire) const;
bool checkPipAvail(PipId pip) const;
diff --git a/ecp5/arch_pybindings.h b/ecp5/arch_pybindings.h
index 6256af18..a5044f29 100644
--- a/ecp5/arch_pybindings.h
+++ b/ecp5/arch_pybindings.h
@@ -30,11 +30,7 @@ namespace PythonConversion {
template <> struct string_converter<BelId>
{
- BelId from_str(Context *ctx, std::string name)
- {
- auto &&proxy = ctx->rproxy();
- return proxy.getBelByName(ctx->id(name));
- }
+ BelId from_str(Context *ctx, std::string name) { return ctx->getBelByName(ctx->id(name)); }
std::string to_str(Context *ctx, BelId id)
{
@@ -53,22 +49,14 @@ template <> struct string_converter<BelType>
template <> struct string_converter<WireId>
{
- WireId from_str(Context *ctx, std::string name)
- {
- auto &&proxy = ctx->rproxy();
- return proxy.getWireByName(ctx->id(name));
- }
+ WireId from_str(Context *ctx, std::string name) { return ctx->getWireByName(ctx->id(name)); }
std::string to_str(Context *ctx, WireId id) { return ctx->getWireName(id).str(ctx); }
};
template <> struct string_converter<PipId>
{
- PipId from_str(Context *ctx, std::string name)
- {
- auto &&proxy = ctx->rproxy();
- return proxy.getPipByName(ctx->id(name));
- }
+ PipId from_str(Context *ctx, std::string name) { return ctx->getPipByName(ctx->id(name)); }
std::string to_str(Context *ctx, PipId id) { return ctx->getPipName(id).str(ctx); }
};
diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc
index b2376391..e70d6bb2 100644
--- a/ecp5/bitstream.cc
+++ b/ecp5/bitstream.cc
@@ -155,7 +155,6 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
{
Trellis::Chip empty_chip(ctx->getChipName());
Trellis::ChipConfig cc;
- auto &&proxy = ctx->rproxy();
std::set<std::string> cib_tiles = {"CIB", "CIB_LR", "CIB_LR_S", "CIB_EFB0", "CIB_EFB1"};
@@ -173,7 +172,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
// Add all set, configurable pips to the config
for (auto pip : ctx->getPips()) {
- if (proxy.getBoundPipNet(pip) != IdString()) {
+ if (ctx->getBoundPipNet(pip) != IdString()) {
if (ctx->getPipType(pip) == 0) { // ignore fixed pips
std::string tile = empty_chip.get_tile_by_position_and_type(pip.location.y, pip.location.x,
ctx->getPipTiletype(pip));
@@ -228,7 +227,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
(ci->ports.find(ctx->id("T")) == ci->ports.end() || ci->ports.at(ctx->id("T")).net == nullptr)) {
// Tie tristate low if unconnected for outputs or bidir
std::string jpt = fmt_str("X" << bel.location.x << "/Y" << bel.location.y << "/JPADDT" << pio.back());
- WireId jpt_wire = proxy.getWireByName(ctx->id(jpt));
+ WireId jpt_wire = ctx->getWireByName(ctx->id(jpt));
PipId jpt_pip = *ctx->getPipsUphill(jpt_wire).begin();
WireId cib_wire = ctx->getPipSrcWire(jpt_pip);
std::string cib_tile =
diff --git a/gui/designwidget.cc b/gui/designwidget.cc
index e839f006..110cf1b7 100644
--- a/gui/designwidget.cc
+++ b/gui/designwidget.cc
@@ -335,12 +335,10 @@ void DesignWidget::onItemClicked(QTreeWidgetItem *clickItem, int pos)
return;
}
- auto &&proxy = ctx->rproxy();
-
clearProperties();
if (type == ElementType::BEL) {
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
- BelId bel = proxy.getBelByName(c);
+ BelId bel = ctx->getBelByName(c);
QtProperty *topItem = groupManager->addProperty("Bel");
addProperty(topItem, "Bel");
@@ -354,20 +352,20 @@ void DesignWidget::onItemClicked(QTreeWidgetItem *clickItem, int pos)
topItem->addSubProperty(typeItem);
QtVariantProperty *availItem = readOnlyManager->addProperty(QVariant::Bool, "Available");
- availItem->setValue(proxy.checkBelAvail(bel));
+ availItem->setValue(ctx->checkBelAvail(bel));
topItem->addSubProperty(availItem);
QtVariantProperty *cellItem = readOnlyManager->addProperty(QVariant::String, "Bound Cell");
- cellItem->setValue(proxy.getBoundBelCell(bel).c_str(ctx));
+ cellItem->setValue(ctx->getBoundBelCell(bel).c_str(ctx));
topItem->addSubProperty(cellItem);
QtVariantProperty *conflictItem = readOnlyManager->addProperty(QVariant::String, "Conflicting Cell");
- conflictItem->setValue(proxy.getConflictingBelCell(bel).c_str(ctx));
+ conflictItem->setValue(ctx->getConflictingBelCell(bel).c_str(ctx));
topItem->addSubProperty(conflictItem);
} else if (type == ElementType::WIRE) {
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
- WireId wire = proxy.getWireByName(c);
+ WireId wire = ctx->getWireByName(c);
QtProperty *topItem = groupManager->addProperty("Wire");
addProperty(topItem, "Wire");
@@ -377,15 +375,15 @@ void DesignWidget::onItemClicked(QTreeWidgetItem *clickItem, int pos)
topItem->addSubProperty(nameItem);
QtVariantProperty *availItem = readOnlyManager->addProperty(QVariant::Bool, "Available");
- availItem->setValue(proxy.checkWireAvail(wire));
+ availItem->setValue(ctx->checkWireAvail(wire));
topItem->addSubProperty(availItem);
QtVariantProperty *cellItem = readOnlyManager->addProperty(QVariant::String, "Bound Net");
- cellItem->setValue(proxy.getBoundWireNet(wire).c_str(ctx));
+ cellItem->setValue(ctx->getBoundWireNet(wire).c_str(ctx));
topItem->addSubProperty(cellItem);
QtVariantProperty *conflictItem = readOnlyManager->addProperty(QVariant::String, "Conflicting Net");
- conflictItem->setValue(proxy.getConflictingWireNet(wire).c_str(ctx));
+ conflictItem->setValue(ctx->getConflictingWireNet(wire).c_str(ctx));
topItem->addSubProperty(conflictItem);
BelPin uphill = ctx->getBelPinUphill(wire);
@@ -441,7 +439,7 @@ void DesignWidget::onItemClicked(QTreeWidgetItem *clickItem, int pos)
} else if (type == ElementType::PIP) {
IdString c = static_cast<IdStringTreeItem *>(clickItem)->getData();
- PipId pip = proxy.getPipByName(c);
+ PipId pip = ctx->getPipByName(c);
QtProperty *topItem = groupManager->addProperty("Pip");
addProperty(topItem, "Pip");
@@ -451,15 +449,15 @@ void DesignWidget::onItemClicked(QTreeWidgetItem *clickItem, int pos)
topItem->addSubProperty(nameItem);
QtVariantProperty *availItem = readOnlyManager->addProperty(QVariant::Bool, "Available");
- availItem->setValue(proxy.checkPipAvail(pip));
+ availItem->setValue(ctx->checkPipAvail(pip));
topItem->addSubProperty(availItem);
QtVariantProperty *cellItem = readOnlyManager->addProperty(QVariant::String, "Bound Net");
- cellItem->setValue(proxy.getBoundPipNet(pip).c_str(ctx));
+ cellItem->setValue(ctx->getBoundPipNet(pip).c_str(ctx));
topItem->addSubProperty(cellItem);
QtVariantProperty *conflictItem = readOnlyManager->addProperty(QVariant::String, "Conflicting Net");
- conflictItem->setValue(proxy.getConflictingPipNet(pip).c_str(ctx));
+ conflictItem->setValue(ctx->getConflictingPipNet(pip).c_str(ctx));
topItem->addSubProperty(conflictItem);
QtVariantProperty *srcWireItem = readOnlyManager->addProperty(QVariant::String, "Src Wire");
diff --git a/ice40/arch.h b/ice40/arch.h
index ec1e456f..cdee92e4 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -578,7 +578,6 @@ class Arch : public BaseCtx
// -------------------------------------------------
- // TODO(q3k) move this to archproxies?
DecalXY getFrameDecal() const;
DecalXY getBelDecal(BelId bel) const;
DecalXY getWireDecal(WireId wire) const;
diff --git a/ice40/picorv32.sh b/ice40/picorv32.sh
index 0518db83..2c67f641 100755
--- a/ice40/picorv32.sh
+++ b/ice40/picorv32.sh
@@ -1,6 +1,6 @@
#!/bin/bash
set -ex
-#rm -f picorv32.v
-#wget https://raw.githubusercontent.com/cliffordwolf/picorv32/master/picorv32.v
-#yosys -p 'synth_ice40 -nocarry -json picorv32.json -top top' picorv32.v picorv32_top.v
-CPUPROFILE=../profile ../nextpnr-ice40 --hx8k --asc picorv32.asc --json picorv32.json
+rm -f picorv32.v
+wget https://raw.githubusercontent.com/cliffordwolf/picorv32/master/picorv32.v
+yosys -p 'synth_ice40 -nocarry -json picorv32.json -top top' picorv32.v picorv32_top.v
+../nextpnr-ice40 --hx8k --asc picorv32.asc --json picorv32.json