nexus: Added support for the DCS Bel

Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
This commit is contained in:
Maciej Kurc 2022-03-11 16:05:37 +01:00
parent 74783c0c09
commit 43861c0ee2
5 changed files with 57 additions and 3 deletions

View File

@ -486,6 +486,12 @@ bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort
if (fromPort == id_CLK)
return false; // don't include delays that are actually clock-to-out here
return lookup_cell_delay(cell->tmg_index, lookup_port(fromPort), lookup_port(toPort), delay);
} else if(cell->type == id_DCS) {
if (fromPort == id_SELFORCE || fromPort == id_SEL) {
return false;
}
int index = get_cell_timing_idx(id_DCS, id_DCS);
return lookup_cell_delay(index, fromPort, toPort, delay);
}
return false;
}
@ -553,6 +559,15 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in
return TMG_GEN_CLOCK;
else if (port == id_CE)
return TMG_COMB_INPUT;
} else if (cell->type == id_DCS) {
// FIXME: Making inputs TMG_CLOCK_INPUT and the output TMG_CLOCK_GEN
// yielded in error in the timing analyzer. For now keep those as
// regular combinational ports.
if (port == id_CLK0 || port == id_CLK1)
return TMG_COMB_INPUT;
else if (port == id_DCSOUT) {
return TMG_COMB_OUTPUT;
}
return TMG_IGNORE;
}
return TMG_IGNORE;

View File

@ -532,6 +532,13 @@ X(SCLK)
X(LOCAL_VCC)
X(DCS)
X(CLK0)
X(CLK1)
X(SELFORCE)
X(DCSOUT)
X(DCSMODE)
X(BEL_TYPE)
X(BEL_Z)
X(CEOUTMUX)

View File

@ -536,6 +536,15 @@ struct NexusFasmWriter
write_cell_muxes(cell);
pop(2);
}
// Write config for DCS
void write_dcs(const CellInfo *cell)
{
BelId bel = cell->bel;
push_tile(bel.tile, ctx->id("CMUX_0"));
push_belname(bel);
write_enum(cell, "DCSMODE", "VCC");
pop(2);
}
// Write config for an OXIDE_EBR cell
void write_bram(const CellInfo *cell)
{
@ -939,6 +948,8 @@ struct NexusFasmWriter
write_iol(ci);
else if (ci->type == id_DCC)
write_dcc(ci);
else if (ci->type == id_DCS)
write_dcs(ci);
blank();
}
// Handle DCC route-throughs

View File

@ -193,7 +193,7 @@ struct NexusGlobalRouter
CellInfo *drv = ni->driver.cell;
if (drv == nullptr)
continue;
if (drv->type == id_DCC) {
if (drv->type == id_DCC || drv->type == id_DCS) {
route_clk_net(ni);
continue;
}

View File

@ -860,6 +860,9 @@ struct NexusPacker
// Skip undriven nets; and nets that are already global
if (ni->driver.cell == nullptr)
continue;
if (ni->driver.cell->type == id_DCS) {
continue;
}
if (ni->driver.cell->type == id_DCC) {
--available_globals;
continue;
@ -1981,14 +1984,32 @@ struct NexusPacker
if (user.port == id_CLKI || user.port == id_REFCK)
changed_cells.insert(user.cell->name);
auto &drv = ctx->nets.at(net)->driver;
if (iter == 1 && drv.cell != nullptr && (drv.port == id_HFCLKOUT || drv.port == id_LFCLKOUT))
changed_cells.insert(drv.cell->name);
if (iter == 1 && drv.cell != nullptr) {
if (drv.cell->type == id_OSC_CORE && (drv.port == id_HFCLKOUT || drv.port == id_LFCLKOUT))
changed_cells.insert(drv.cell->name);
if (drv.cell->type == id_DCC && drv.port == id_CLKO)
changed_cells.insert(drv.cell->name);
if (drv.cell->type == id_DCS && drv.port == id_DCSOUT)
changed_cells.insert(drv.cell->name);
}
}
changed_nets.clear();
for (auto cell : changed_cells) {
CellInfo *ci = ctx->cells.at(cell).get();
if (ci->type == id_DCC) {
copy_constraint(ci, id_CLKI, id_CLKO, 1);
} else if (ci->type == id_DCS) {
// For DCC copy the worst case ("fastest") constraint
delay_t period_clk0, period_clk1;
bool have_clk0 = get_period(ci, id_CLK0, period_clk0);
bool have_clk1 = get_period(ci, id_CLK1, period_clk1);
if (have_clk0 && !have_clk1) {
copy_constraint(ci, id_CLK0, id_DCSOUT);
} else if (!have_clk0 && have_clk1) {
copy_constraint(ci, id_CLK1, id_DCSOUT);
} else if ( have_clk0 && have_clk1) {
set_period(ci, id_DCSOUT, std::min(period_clk0, period_clk1));
}
} else if (ci->type == id_OSC_CORE) {
int div = int_or_default(ci->params, id_HF_CLK_DIV, 128);
const float tol = 1.07f; // OSCA has +/-7% frequency tolerance, assume the worst case.