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)
|
if (fromPort == id_CLK)
|
||||||
return false; // don't include delays that are actually clock-to-out here
|
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);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
@ -553,6 +559,15 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in
|
|||||||
return TMG_GEN_CLOCK;
|
return TMG_GEN_CLOCK;
|
||||||
else if (port == id_CE)
|
else if (port == id_CE)
|
||||||
return TMG_COMB_INPUT;
|
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;
|
||||||
}
|
}
|
||||||
return TMG_IGNORE;
|
return TMG_IGNORE;
|
||||||
|
@ -532,6 +532,13 @@ X(SCLK)
|
|||||||
|
|
||||||
X(LOCAL_VCC)
|
X(LOCAL_VCC)
|
||||||
|
|
||||||
|
X(DCS)
|
||||||
|
X(CLK0)
|
||||||
|
X(CLK1)
|
||||||
|
X(SELFORCE)
|
||||||
|
X(DCSOUT)
|
||||||
|
X(DCSMODE)
|
||||||
|
|
||||||
X(BEL_TYPE)
|
X(BEL_TYPE)
|
||||||
X(BEL_Z)
|
X(BEL_Z)
|
||||||
X(CEOUTMUX)
|
X(CEOUTMUX)
|
||||||
|
@ -536,6 +536,15 @@ struct NexusFasmWriter
|
|||||||
write_cell_muxes(cell);
|
write_cell_muxes(cell);
|
||||||
pop(2);
|
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
|
// Write config for an OXIDE_EBR cell
|
||||||
void write_bram(const CellInfo *cell)
|
void write_bram(const CellInfo *cell)
|
||||||
{
|
{
|
||||||
@ -939,6 +948,8 @@ struct NexusFasmWriter
|
|||||||
write_iol(ci);
|
write_iol(ci);
|
||||||
else if (ci->type == id_DCC)
|
else if (ci->type == id_DCC)
|
||||||
write_dcc(ci);
|
write_dcc(ci);
|
||||||
|
else if (ci->type == id_DCS)
|
||||||
|
write_dcs(ci);
|
||||||
blank();
|
blank();
|
||||||
}
|
}
|
||||||
// Handle DCC route-throughs
|
// Handle DCC route-throughs
|
||||||
|
@ -193,7 +193,7 @@ struct NexusGlobalRouter
|
|||||||
CellInfo *drv = ni->driver.cell;
|
CellInfo *drv = ni->driver.cell;
|
||||||
if (drv == nullptr)
|
if (drv == nullptr)
|
||||||
continue;
|
continue;
|
||||||
if (drv->type == id_DCC) {
|
if (drv->type == id_DCC || drv->type == id_DCS) {
|
||||||
route_clk_net(ni);
|
route_clk_net(ni);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -860,6 +860,9 @@ struct NexusPacker
|
|||||||
// Skip undriven nets; and nets that are already global
|
// Skip undriven nets; and nets that are already global
|
||||||
if (ni->driver.cell == nullptr)
|
if (ni->driver.cell == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
if (ni->driver.cell->type == id_DCS) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (ni->driver.cell->type == id_DCC) {
|
if (ni->driver.cell->type == id_DCC) {
|
||||||
--available_globals;
|
--available_globals;
|
||||||
continue;
|
continue;
|
||||||
@ -1981,14 +1984,32 @@ struct NexusPacker
|
|||||||
if (user.port == id_CLKI || user.port == id_REFCK)
|
if (user.port == id_CLKI || user.port == id_REFCK)
|
||||||
changed_cells.insert(user.cell->name);
|
changed_cells.insert(user.cell->name);
|
||||||
auto &drv = ctx->nets.at(net)->driver;
|
auto &drv = ctx->nets.at(net)->driver;
|
||||||
if (iter == 1 && drv.cell != nullptr && (drv.port == id_HFCLKOUT || drv.port == id_LFCLKOUT))
|
if (iter == 1 && drv.cell != nullptr) {
|
||||||
changed_cells.insert(drv.cell->name);
|
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();
|
changed_nets.clear();
|
||||||
for (auto cell : changed_cells) {
|
for (auto cell : changed_cells) {
|
||||||
CellInfo *ci = ctx->cells.at(cell).get();
|
CellInfo *ci = ctx->cells.at(cell).get();
|
||||||
if (ci->type == id_DCC) {
|
if (ci->type == id_DCC) {
|
||||||
copy_constraint(ci, id_CLKI, id_CLKO, 1);
|
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) {
|
} else if (ci->type == id_OSC_CORE) {
|
||||||
int div = int_or_default(ci->params, id_HF_CLK_DIV, 128);
|
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.
|
const float tol = 1.07f; // OSCA has +/-7% frequency tolerance, assume the worst case.
|
||||||
|
Loading…
Reference in New Issue
Block a user