diff options
author | David Shah <dave@ds0.me> | 2020-11-11 13:42:23 +0000 |
---|---|---|
committer | David Shah <dave@ds0.me> | 2020-11-30 08:45:28 +0000 |
commit | 530d6ce9e9528e6067e679323694fbc1617586d8 (patch) | |
tree | 0f409425937bb9019ecbeb72f1c83528c162eb10 /nexus | |
parent | 9b89a82573500118269515154265f811cef6191c (diff) | |
download | nextpnr-530d6ce9e9528e6067e679323694fbc1617586d8.tar.gz nextpnr-530d6ce9e9528e6067e679323694fbc1617586d8.tar.bz2 nextpnr-530d6ce9e9528e6067e679323694fbc1617586d8.zip |
nexus: Add EBR timing analysis
Signed-off-by: David Shah <dave@ds0.me>
Diffstat (limited to 'nexus')
-rw-r--r-- | nexus/arch.cc | 19 | ||||
-rw-r--r-- | nexus/pack.cc | 19 |
2 files changed, 38 insertions, 0 deletions
diff --git a/nexus/arch.cc b/nexus/arch.cc index 5cd8ab9b..f4a88dfb 100644 --- a/nexus/arch.cc +++ b/nexus/arch.cc @@ -491,12 +491,23 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in clockInfoCount = 1; return TMG_REGISTER_INPUT; } + } else if (cell->type == id_OXIDE_EBR) { + if (port == id_DWS0 || port == id_DWS1 || port == id_DWS2 || port == id_DWS3 || port == id_DWS4) + return TMG_IGNORE; + if (port == id_CLKA || port == id_CLKB) + return TMG_CLOCK_INPUT; + clockInfoCount = 1; + return (cell->ports.at(port).type == PORT_IN) ? TMG_REGISTER_INPUT : TMG_REGISTER_OUTPUT; } return TMG_IGNORE; } TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port, int index) const { + auto lookup_port = [&](IdString p) { + auto fnd = cell->tmg_portmap.find(p); + return fnd == cell->tmg_portmap.end() ? p : fnd->second; + }; TimingClockingInfo info; if (cell->type == id_OXIDE_FF) { info.edge = (cell->ffInfo.ctrlset.clkmux == ID_INV) ? FALLING_EDGE : RISING_EDGE; @@ -512,6 +523,14 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port NPNR_ASSERT(lookup_cell_delay(cell->tmg_index, id_CLK, port, info.clockToQ)); else lookup_cell_setuphold(cell->tmg_index, port, id_CLK, info.setup, info.hold); + } else if (cell->type == id_OXIDE_EBR) { + if (cell->ports.at(port).type == PORT_IN) { + lookup_cell_setuphold_clock(cell->tmg_index, lookup_port(port), info.clock_port, info.setup, info.hold); + } else { + lookup_cell_clock_out(cell->tmg_index, lookup_port(port), info.clock_port, info.clockToQ); + } + // Lookup edge based on inversion + info.edge = (get_cell_pinmux(cell, info.clock_port) == PINMUX_INV) ? FALLING_EDGE : RISING_EDGE; } else { NPNR_ASSERT_FALSE("missing clocking info"); } diff --git a/nexus/pack.cc b/nexus/pack.cc index bfa45d38..260dcf19 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -1306,6 +1306,25 @@ void Arch::assignCellInfo(CellInfo *cell) cell->ffInfo.di = nullptr; cell->ffInfo.m = nullptr; cell->tmg_index = get_cell_timing_idx(id_RAMW); + } else if (cell->type == id_OXIDE_EBR) { + // Strip off bus indices to get the timing ports + // as timing is generally word-wide + for (const auto &port : cell->ports) { + const std::string &name = port.first.str(this); + size_t idx_end = name.find_last_not_of("0123456789"); + std::string base = name.substr(0, idx_end + 1); + if (base == "ADA" || base == "ADB") { + // [4:0] and [13:5] have different timing + int idx = std::stoi(name.substr(idx_end + 1)); + cell->tmg_portmap[port.first] = id(base + ((idx >= 5) ? "_13_5" : "_4_0")); + } else { + // Just strip off bus index + cell->tmg_portmap[port.first] = id(base); + } + } + + cell->tmg_index = get_cell_timing_idx(id(str_or_default(cell->params, id_MODE, "DP16K") + "_MODE")); + NPNR_ASSERT(cell->tmg_index != -1); } } |