aboutsummaryrefslogtreecommitdiffstats
path: root/ice40
diff options
context:
space:
mode:
Diffstat (limited to 'ice40')
-rw-r--r--ice40/arch.cc39
-rw-r--r--ice40/arch.h15
-rw-r--r--ice40/chipdb.py73
-rw-r--r--ice40/main.cc15
4 files changed, 118 insertions, 24 deletions
diff --git a/ice40/arch.cc b/ice40/arch.cc
index 2867f591..eff1d9b9 100644
--- a/ice40/arch.cc
+++ b/ice40/arch.cc
@@ -834,28 +834,23 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const
{
- if (cell->type == id_icestorm_lc) {
- if ((fromPort == id_i0 || fromPort == id_i1 || fromPort == id_i2 || fromPort == id_i3) &&
- (toPort == id_o || toPort == id_lo)) {
- delay.delay = 450;
- return true;
- } else if (fromPort == id_cin && toPort == id_cout) {
- delay.delay = 120;
- return true;
- } else if (fromPort == id_i1 && toPort == id_cout) {
- delay.delay = 260;
- return true;
- } else if (fromPort == id_i2 && toPort == id_cout) {
- delay.delay = 230;
- return true;
- } else if (fromPort == id_clk && toPort == id_o) {
- delay.delay = 540;
- return true;
- }
- } else if (cell->type == id_icestorm_ram) {
- if (fromPort == id_rclk) {
- delay.delay = 2140;
- return true;
+ BelType type = belTypeFromId(cell->type);
+ for (int i = 0; i < chip_info->num_timing_cells; i++) {
+ const auto &tc = chip_info->cell_timing[i];
+ if (tc.type == type) {
+ PortPin fromPin = portPinFromId(fromPort);
+ PortPin toPin = portPinFromId(toPort);
+ for (int j = 0; j < tc.num_paths; j++) {
+ const auto &path = tc.path_delays[j];
+ if (path.from_port == fromPin && path.to_port == toPin) {
+ if (fast_part)
+ delay.delay = path.fast_delay;
+ else
+ delay.delay = path.slow_delay;
+ return true;
+ }
+ }
+ break;
}
}
return false;
diff --git a/ice40/arch.h b/ice40/arch.h
index 4459af60..98361132 100644
--- a/ice40/arch.h
+++ b/ice40/arch.h
@@ -173,10 +173,24 @@ NPNR_PACKED_STRUCT(struct BelConfigPOD {
RelPtr<BelConfigEntryPOD> entries;
});
+NPNR_PACKED_STRUCT(struct CellPathDelayPOD {
+ PortPin from_port;
+ PortPin to_port;
+ int32_t fast_delay;
+ int32_t slow_delay;
+});
+
+NPNR_PACKED_STRUCT(struct CellTimingPOD {
+ int32_t type;
+ int32_t num_paths;
+ RelPtr<CellPathDelayPOD> path_delays;
+});
+
NPNR_PACKED_STRUCT(struct ChipInfoPOD {
int32_t width, height;
int32_t num_bels, num_wires, num_pips;
int32_t num_switches, num_belcfgs, num_packages;
+ int32_t num_timing_cells;
RelPtr<BelInfoPOD> bel_data;
RelPtr<WireInfoPOD> wire_data;
RelPtr<PipInfoPOD> pip_data;
@@ -184,6 +198,7 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD {
RelPtr<BitstreamInfoPOD> bits_info;
RelPtr<BelConfigPOD> bel_config;
RelPtr<PackageInfoPOD> packages_data;
+ RelPtr<CellTimingPOD> cell_timing;
});
#if defined(_MSC_VER)
diff --git a/ice40/chipdb.py b/ice40/chipdb.py
index cb336d0a..a0d7f03c 100644
--- a/ice40/chipdb.py
+++ b/ice40/chipdb.py
@@ -696,6 +696,60 @@ def add_bel_ec(ec):
else:
extra_cell_config[bel].append(entry)
+cell_timings = {}
+tmport_to_portpin = {
+ "posedge:clk": "CLK",
+ "ce": "CEN",
+ "sr": "SR",
+ "in0": "I0",
+ "in1": "I1",
+ "in2": "I2",
+ "in3": "I3",
+ "carryin": "CIN",
+ "carryout": "COUT",
+ "lcout": "O",
+ "ltout": "LO",
+ "posedge:RCLK": "RCLK",
+ "posedge:WCLK": "WCLK",
+ "RCLKE": "RCLKE",
+ "RE": "RE",
+ "WCLKE": "WCLKE",
+ "WE": "WE",
+ "posedge:CLOCK": "CLOCK",
+ "posedge:SLEEP": "SLEEP"
+}
+
+for i in range(16):
+ tmport_to_portpin["RDATA[%d]" % i] = "RDATA_%d" % i
+ tmport_to_portpin["WDATA[%d]" % i] = "WDATA_%d" % i
+ tmport_to_portpin["MASK[%d]" % i] = "MASK_%d" % i
+ tmport_to_portpin["DATAOUT[%d]" % i] = "DATAOUT_%d" % i
+
+for i in range(11):
+ tmport_to_portpin["RADDR[%d]" % i] = "RADDR_%d" % i
+ tmport_to_portpin["WADDR[%d]" % i] = "WADDR_%d" % i
+
+def add_cell_timingdata(bel_type, timing_cell, fast_db, slow_db):
+ timing_entries = []
+ database = slow_db if slow_db is not None else fast_db
+ for key in database.keys():
+ skey = key.split(".")
+ if skey[0] == timing_cell:
+ if skey[1] in tmport_to_portpin and skey[2] in tmport_to_portpin:
+ iport = tmport_to_portpin[skey[1]]
+ oport = tmport_to_portpin[skey[2]]
+ fastdel = fast_db[key] if fast_db is not None else 0
+ slowdel = slow_db[key] if slow_db is not None else 0
+ timing_entries.append((iport, oport, fastdel, slowdel))
+ cell_timings[bel_type] = timing_entries
+
+add_cell_timingdata("ICESTORM_LC", "LogicCell40", fast_timings, slow_timings)
+if dev_name != "384":
+ add_cell_timingdata("ICESTORM_RAM", "SB_RAM40_4K", fast_timings, slow_timings)
+if dev_name == "5k":
+ add_cell_timingdata("SPRAM", "SB_SPRAM256KA", fast_timings, slow_timings)
+
+
for tile_xy, tile_type in sorted(tiles.items()):
if tile_type == "logic":
for i in range(8):
@@ -1109,6 +1163,23 @@ for info in packageinfo:
bba.u32(info[1], "num_pins")
bba.r(info[2], "pins")
+for cell, timings in sorted(cell_timings.items()):
+ beltype = beltypes[cell]
+ bba.l("cell_paths_%d" % beltype, "CellPathDelayPOD")
+ for entry in timings:
+ fromport, toport, fast, slow = entry
+ bba.u32(portpins[fromport], "from_port")
+ bba.u32(portpins[toport], "to_port")
+ bba.u32(fast, "fast_delay")
+ bba.u32(slow, "slow_delay")
+
+bba.l("cell_timings_%s" % dev_name, "CellTimingPOD")
+for cell, timings in sorted(cell_timings.items()):
+ beltype = beltypes[cell]
+ bba.u32(beltype, "type")
+ bba.u32(len(timings), "num_paths")
+ bba.r("cell_paths_%d" % beltype, "path_delays")
+
bba.l("chip_info_%s" % dev_name)
bba.u32(dev_width, "dev_width")
bba.u32(dev_height, "dev_height")
@@ -1118,6 +1189,7 @@ bba.u32(len(pipinfo), "num_pips")
bba.u32(len(switchinfo), "num_switches")
bba.u32(len(extra_cell_config), "num_belcfgs")
bba.u32(len(packageinfo), "num_packages")
+bba.u32(len(cell_timings), "num_timing_cells")
bba.r("bel_data_%s" % dev_name, "bel_data")
bba.r("wire_data_%s" % dev_name, "wire_data")
bba.r("pip_data_%s" % dev_name, "pip_data")
@@ -1125,5 +1197,6 @@ bba.r("tile_grid_%s" % dev_name, "tile_grid")
bba.r("bits_info_%s" % dev_name, "bits_info")
bba.r("bel_config_%s" % dev_name if len(extra_cell_config) > 0 else None, "bel_config")
bba.r("package_info_%s" % dev_name, "packages_data")
+bba.r("cell_timings_%s" % dev_name, "cell_timing")
bba.pop()
diff --git a/ice40/main.cc b/ice40/main.cc
index 0724acdf..4a2e9532 100644
--- a/ice40/main.cc
+++ b/ice40/main.cc
@@ -168,6 +168,11 @@ int main(int argc, char *argv[])
pt::read_json(filename, root);
log_info("Loading project %s...\n", filename.c_str());
log_break();
+
+ bool isLoadingGui = vm.count("gui") > 0;
+ std::string ascOutput;
+ if (vm.count("asc"))
+ ascOutput = vm["asc"].as<std::string>();
vm.clear();
int version = root.get<int>("project.version");
@@ -199,6 +204,10 @@ int main(int argc, char *argv[])
if (params.count("seed"))
vm.insert(std::make_pair("seed", po::variable_value(params.get<int>("seed"), false)));
}
+ if (!ascOutput.empty())
+ vm.insert(std::make_pair("asc", po::variable_value(ascOutput, false)));
+ if (isLoadingGui)
+ vm.insert(std::make_pair("gui", po::variable_value()));
po::notify(vm);
} catch (...) {
log_error("Error loading project file.\n");
@@ -397,9 +406,11 @@ int main(int argc, char *argv[])
if (vm.count("json")) {
std::string filename = vm["json"].as<std::string>();
std::string pcf = "";
- if (vm.count("pcf"))
+ w.load_json(filename);
+ if (vm.count("pcf")) {
pcf = vm["pcf"].as<std::string>();
- w.load_json(filename, pcf);
+ w.load_pcf(pcf);
+ }
}
w.show();