nexus: Add EBR timing analysis
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
9b89a82573
commit
530d6ce9e9
@ -491,12 +491,23 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in
|
|||||||
clockInfoCount = 1;
|
clockInfoCount = 1;
|
||||||
return TMG_REGISTER_INPUT;
|
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;
|
return TMG_IGNORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port, int index) const
|
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;
|
TimingClockingInfo info;
|
||||||
if (cell->type == id_OXIDE_FF) {
|
if (cell->type == id_OXIDE_FF) {
|
||||||
info.edge = (cell->ffInfo.ctrlset.clkmux == ID_INV) ? FALLING_EDGE : RISING_EDGE;
|
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));
|
NPNR_ASSERT(lookup_cell_delay(cell->tmg_index, id_CLK, port, info.clockToQ));
|
||||||
else
|
else
|
||||||
lookup_cell_setuphold(cell->tmg_index, port, id_CLK, info.setup, info.hold);
|
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 {
|
} else {
|
||||||
NPNR_ASSERT_FALSE("missing clocking info");
|
NPNR_ASSERT_FALSE("missing clocking info");
|
||||||
}
|
}
|
||||||
|
@ -1306,6 +1306,25 @@ void Arch::assignCellInfo(CellInfo *cell)
|
|||||||
cell->ffInfo.di = nullptr;
|
cell->ffInfo.di = nullptr;
|
||||||
cell->ffInfo.m = nullptr;
|
cell->ffInfo.m = nullptr;
|
||||||
cell->tmg_index = get_cell_timing_idx(id_RAMW);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user