diff options
Diffstat (limited to 'ice40')
-rw-r--r-- | ice40/arch.h | 6 | ||||
-rw-r--r-- | ice40/archdefs.h | 11 | ||||
-rw-r--r-- | ice40/bitstream.cc | 169 | ||||
-rw-r--r-- | ice40/blinky.proj | 3 | ||||
-rw-r--r-- | ice40/main.cc | 6 | ||||
-rw-r--r-- | ice40/picorv32.proj | 15 | ||||
-rwxr-xr-x | ice40/picorv32.sh | 1 |
7 files changed, 193 insertions, 18 deletions
diff --git a/ice40/arch.h b/ice40/arch.h index beba2ccf..21169298 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -548,6 +548,12 @@ struct Arch : BaseCtx return wire_to_net[wire.index]; } + DelayInfo getWireDelay(WireId wire) const + { + DelayInfo delay; + return delay; + } + WireRange getWires() const { WireRange range; diff --git a/ice40/archdefs.h b/ice40/archdefs.h index dec6f702..8a7449a8 100644 --- a/ice40/archdefs.h +++ b/ice40/archdefs.h @@ -29,9 +29,14 @@ struct DelayInfo { delay_t delay = 0; - delay_t raiseDelay() const { return delay; } - delay_t fallDelay() const { return delay; } - delay_t avgDelay() const { return delay; } + delay_t minRaiseDelay() const { return delay; } + delay_t maxRaiseDelay() const { return delay; } + + delay_t minFallDelay() const { return delay; } + delay_t maxFallDelay() const { return delay; } + + delay_t minDelay() const { return delay; } + delay_t maxDelay() const { return delay; } DelayInfo operator+(const DelayInfo &other) const { diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index 924868b5..7fd3f8ac 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -20,6 +20,7 @@ #include "bitstream.h"
#include <cctype>
#include <vector>
+#include "cells.h"
#include "log.h"
NEXTPNR_NAMESPACE_BEGIN
@@ -51,6 +52,20 @@ std::tuple<int8_t, int8_t, int8_t> get_ieren(const BitstreamInfoPOD &bi, int8_t return std::make_tuple(-1, -1, -1);
};
+bool get_config(const TileInfoPOD &ti, std::vector<std::vector<int8_t>> &tile_cfg, const std::string &name,
+ int index = -1)
+{
+ const ConfigEntryPOD &cfg = find_config(ti, name);
+ if (index == -1) {
+ for (int i = 0; i < cfg.num_bits; i++) {
+ return tile_cfg.at(cfg.bits[i].row).at(cfg.bits[i].col);
+ }
+ } else {
+ return tile_cfg.at(cfg.bits[index].row).at(cfg.bits[index].col);
+ }
+ return false;
+}
+
void set_config(const TileInfoPOD &ti, std::vector<std::vector<int8_t>> &tile_cfg, const std::string &name, bool value,
int index = -1)
{
@@ -467,9 +482,8 @@ void write_asc(const Context *ctx, std::ostream &out) set_config(ti, config.at(y).at(x),
"Cascade.IPCON_LC0" + std::to_string(lc_idx) + "_inmux02_5", true);
else
- set_config(ti, config.at(y).at(x),
- "Cascade.MULT" + std::to_string(int(tile - TILE_DSP0)) + "_LC0" +
- std::to_string(lc_idx) + "_inmux02_5",
+ set_config(ti, config.at(y).at(x), "Cascade.MULT" + std::to_string(int(tile - TILE_DSP0)) +
+ "_LC0" + std::to_string(lc_idx) + "_inmux02_5",
true);
}
}
@@ -588,15 +602,18 @@ void read_config(Context *ctx, std::istream &in, chipconfig_t &config) std::tuple<int, int, int> key(b, x, y);
extra_bits.insert(key);
*/
- } else if (!strcmp(tok, ".sym")) {
+ } else if (!strcmp(tok, ".sym")) {
int wireIndex = atoi(strtok(nullptr, " \t\r\n"));
const char *name = strtok(nullptr, " \t\r\n");
-
- std::unique_ptr<NetInfo> created_net = std::unique_ptr<NetInfo>(new NetInfo);
+
IdString netName = ctx->id(name);
- created_net->name = netName;
- ctx->nets[netName] = std::move(created_net);
-
+
+ if (ctx->nets.find(netName) == ctx->nets.end()) {
+ std::unique_ptr<NetInfo> created_net = std::unique_ptr<NetInfo>(new NetInfo);
+ created_net->name = netName;
+ ctx->nets[netName] = std::move(created_net);
+ }
+
WireId wire;
wire.index = wireIndex;
ctx->bindWire(wire, netName, STRENGTH_WEAK);
@@ -630,7 +647,139 @@ bool read_asc(Context *ctx, std::istream &in) config.at(y).at(x).resize(rows, std::vector<int8_t>(cols));
}
}
- read_config(ctx, in, config);
+ read_config(ctx, in, config);
+
+ // Set pips
+ for (auto pip : ctx->getPips()) {
+ const PipInfoPOD &pi = ci.pip_data[pip.index];
+ const SwitchInfoPOD &swi = bi.switches[pi.switch_index];
+ bool isUsed = true;
+ for (int i = 0; i < swi.num_bits; i++) {
+ bool val = (pi.switch_mask & (1 << ((swi.num_bits - 1) - i))) != 0;
+ int8_t cbit = config.at(swi.y).at(swi.x).at(swi.cbits[i].row).at(swi.cbits[i].col);
+ isUsed &= !(bool(cbit) ^ val);
+ }
+ if (isUsed) {
+ IdString net = ctx->wire_to_net[pi.dst];
+ WireId wire;
+ wire.index = pi.dst;
+ ctx->unbindWire(wire);
+ ctx->bindPip(pip, net, STRENGTH_WEAK);
+ }
+ }
+ for (auto bel : ctx->getBels()) {
+ if (ctx->getBelType(bel) == TYPE_ICESTORM_LC) {
+ const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_LOGIC];
+ const BelInfoPOD &beli = ci.bel_data[bel.index];
+ int x = beli.x, y = beli.y, z = beli.z;
+ std::vector<bool> lc(20, false);
+ bool isUsed = false;
+ for (int i = 0; i < 20; i++) {
+ lc.at(i) = get_config(ti, config.at(y).at(x), "LC_" + std::to_string(z), i);
+ isUsed |= lc.at(i);
+ }
+ bool neg_clk = get_config(ti, config.at(y).at(x), "NegClk");
+ isUsed |= neg_clk;
+ bool carry_set = get_config(ti, config.at(y).at(x), "CarryInSet");
+ isUsed |= carry_set;
+
+ if (isUsed) {
+ std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LC"));
+ IdString name = created->name;
+ ctx->cells[name] = std::move(created);
+ ctx->bindBel(bel, name, STRENGTH_WEAK);
+ // TODO: Add port mapping to nets and assign values of properties
+ }
+ }
+ if (ctx->getBelType(bel) == TYPE_SB_IO) {
+ const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO];
+ const BelInfoPOD &beli = ci.bel_data[bel.index];
+ int x = beli.x, y = beli.y, z = beli.z;
+ bool isUsed = false;
+ for (int i = 0; i < 6; i++) {
+ isUsed |= get_config(ti, config.at(y).at(x),
+ "IOB_" + std::to_string(z) + ".PINTYPE_" + std::to_string(i));
+ }
+ bool neg_trigger = get_config(ti, config.at(y).at(x), "NegClk");
+ isUsed |= neg_trigger;
+
+ if (isUsed) {
+ std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_IO"));
+ IdString name = created->name;
+ ctx->cells[name] = std::move(created);
+ ctx->bindBel(bel, name, STRENGTH_WEAK);
+ // TODO: Add port mapping to nets and assign values of properties
+ }
+ }
+ }
+ // Add cells that are without change in initial state of configuration
+ for (auto &net : ctx->nets) {
+ for (auto w : net.second->wires) {
+ if (w.second.pip == PipId()) {
+ WireId wire = w.first;
+ BelPin belpin = ctx->getBelPinUphill(wire);
+ if (ctx->checkBelAvail(belpin.bel)) {
+ if (ctx->getBelType(belpin.bel) == TYPE_ICESTORM_LC) {
+ std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LC"));
+ IdString name = created->name;
+ ctx->cells[name] = std::move(created);
+ ctx->bindBel(belpin.bel, name, STRENGTH_WEAK);
+ // TODO: Add port mapping to nets
+ }
+ if (ctx->getBelType(belpin.bel) == TYPE_SB_IO) {
+ std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_IO"));
+ IdString name = created->name;
+ ctx->cells[name] = std::move(created);
+ ctx->bindBel(belpin.bel, name, STRENGTH_WEAK);
+ // TODO: Add port mapping to nets
+ }
+ if (ctx->getBelType(belpin.bel) == TYPE_SB_GB) {
+ std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_GB"));
+ IdString name = created->name;
+ ctx->cells[name] = std::move(created);
+ ctx->bindBel(belpin.bel, name, STRENGTH_WEAK);
+ // TODO: Add port mapping to nets
+ }
+ if (ctx->getBelType(belpin.bel) == TYPE_SB_WARMBOOT) {
+ std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_WARMBOOT"));
+ IdString name = created->name;
+ ctx->cells[name] = std::move(created);
+ ctx->bindBel(belpin.bel, name, STRENGTH_WEAK);
+ // TODO: Add port mapping to nets
+ }
+ if (ctx->getBelType(belpin.bel) == TYPE_ICESTORM_LFOSC) {
+ std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC"));
+ IdString name = created->name;
+ ctx->cells[name] = std::move(created);
+ ctx->bindBel(belpin.bel, name, STRENGTH_WEAK);
+ // TODO: Add port mapping to nets
+ }
+ }
+ }
+ }
+ }
+ for (auto &cell : ctx->cells) {
+ if (cell.second->bel != BelId()) {
+ for (auto &port : cell.second->ports) {
+ PortPin pin = ctx->portPinFromId(port.first);
+ WireId wire = ctx->getWireBelPin(cell.second->bel, pin);
+ if (wire != WireId()) {
+ IdString name = ctx->getBoundWireNet(wire);
+ if (name != IdString()) {
+ port.second.net = ctx->nets[name].get();
+ PortRef ref;
+ ref.cell = cell.second.get();
+ ref.port = port.second.name;
+
+ if (port.second.type == PORT_OUT)
+ ctx->nets[name]->driver = ref;
+ else
+ ctx->nets[name]->users.push_back(ref);
+ }
+ }
+ }
+ }
+ }
return true;
} catch (log_execution_error_exception) {
return false;
diff --git a/ice40/blinky.proj b/ice40/blinky.proj index 6789a27a..f5bb9f88 100644 --- a/ice40/blinky.proj +++ b/ice40/blinky.proj @@ -10,9 +10,6 @@ "input": { "json": "blinky.json", "pcf": "blinky.pcf" - }, - "params": { - "freq": "50" } } } diff --git a/ice40/main.cc b/ice40/main.cc index 652196a1..70324a91 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -68,8 +68,10 @@ void svg_dump_decal(const Context *ctx, const DecalXY &decal) void conflicting_options(const boost::program_options::variables_map &vm, const char *opt1, const char *opt2) { - if (vm.count(opt1) && !vm[opt1].defaulted() && vm.count(opt2) && !vm[opt2].defaulted()) - log_error((std::string("Conflicting options '") + opt1 + "' and '" + opt2 + "'.").c_str()); + if (vm.count(opt1) && !vm[opt1].defaulted() && vm.count(opt2) && !vm[opt2].defaulted()) { + std::string msg = "Conflicting options '"+ std::string(opt1) + "' and '" + std::string(opt1) + "'."; + log_error("%s\n",msg.c_str()); + } } int main(int argc, char *argv[]) diff --git a/ice40/picorv32.proj b/ice40/picorv32.proj new file mode 100644 index 00000000..a8c83bd9 --- /dev/null +++ b/ice40/picorv32.proj @@ -0,0 +1,15 @@ +{ + "project": { + "version": "1", + "name": "picorv32", + "arch": { + "name": "ice40", + "type": "hx8k", + "package": "ct256" + }, + "input": { + "json": "picorv32.json", + "pcf": "icebreaker.pcf" + } + } +} diff --git a/ice40/picorv32.sh b/ice40/picorv32.sh index 87426cde..d06786c5 100755 --- a/ice40/picorv32.sh +++ b/ice40/picorv32.sh @@ -4,3 +4,4 @@ rm -f picorv32.v wget https://raw.githubusercontent.com/cliffordwolf/picorv32/master/picorv32.v yosys -p 'synth_ice40 -json picorv32.json -top top' picorv32.v picorv32_top.v ../nextpnr-ice40 --hx8k --asc picorv32.asc --json picorv32.json +icetime -d hx8k -t picorv32.asc |