nexus: Added support for the DCS Bel
Signed-off-by: Maciej Kurc <mkurc@antmicro.com>
This commit is contained in:
parent
74783c0c09
commit
43861c0ee2
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user