mirror of https://github.com/YosysHQ/nextpnr.git
WIP: nexus iodelay
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
9ae5de7c7c
commit
94ac6d087e
|
|
@ -560,6 +560,27 @@ X(RSTSMCLK)
|
|||
|
||||
X(CONFIG_CLKRST_CORE)
|
||||
|
||||
X(DELAYA)
|
||||
X(DELAYB)
|
||||
X(COARSE0)
|
||||
X(COARSE1)
|
||||
X(CIBCRS0)
|
||||
X(CIBCRS1)
|
||||
X(DIRECTION)
|
||||
X(DIR)
|
||||
X(DEL_MODE)
|
||||
X(DEL_VALUE)
|
||||
X(COARSE_DELAY)
|
||||
X(COARSE_DELAY_MODE)
|
||||
X(EDGE_MONITOR)
|
||||
X(WAIT_FOR_EDGE)
|
||||
X(DELAYMUX)
|
||||
X(INMUX)
|
||||
X(OUTMUX)
|
||||
X(DELAY)
|
||||
X(OUT_REG)
|
||||
X(CFLAG)
|
||||
|
||||
X(BEL_TYPE)
|
||||
X(BEL_Z)
|
||||
X(CEOUTMUX)
|
||||
|
|
|
|||
|
|
@ -660,6 +660,17 @@ struct NexusFasmWriter
|
|||
write_enum(cell, "IDDRX1_ODDRX1.TRISTATE");
|
||||
write_enum(cell, "GSR", "DISABLED");
|
||||
write_enum(cell, "TSREG.REGSET", "RESET");
|
||||
if (cell->params.count(ctx->id("DELAY.DEL_VALUE"))) {
|
||||
write_int_vector(stringf("DELAY.DEL_VALUE[6:0]"),
|
||||
int_or_default(cell->params, ctx->id("DELAY.DEL_VALUE"), 0), 7);
|
||||
}
|
||||
write_enum(cell, "DELAY.COARSE_DELAY");
|
||||
write_enum(cell, "DELAY.EDGE_MONITOR");
|
||||
write_enum(cell, "DELAY.WAIT_FOR_EDGE");
|
||||
write_enum(cell, "DELAYMUX");
|
||||
write_enum(cell, "INMUX");
|
||||
write_enum(cell, "OUTMUX");
|
||||
|
||||
write_cell_muxes(cell);
|
||||
pop();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1220,6 +1220,58 @@ struct NexusPacker
|
|||
}
|
||||
}
|
||||
|
||||
void pack_iodelay()
|
||||
{
|
||||
dict<IdString, XFormRule> base_iodelay_rules;
|
||||
base_iodelay_rules[id_DELAYB].new_type = id_IOLOGIC;
|
||||
|
||||
base_iodelay_rules[id_DELAYB].param_xform[id_DEL_VALUE] = ctx->id("DELAY.DEL_VALUE");
|
||||
base_iodelay_rules[id_DELAYB].param_xform[id_COARSE_DELAY] = ctx->id("DELAY.COARSE_DELAY");
|
||||
|
||||
base_iodelay_rules[id_DELAYA] = base_iodelay_rules[id_DELAYB];
|
||||
|
||||
base_iodelay_rules[id_DELAYA].param_xform[id_COARSE_DELAY_MODE] = ctx->id("DELAY.COARSE_DELAY_MODE");
|
||||
base_iodelay_rules[id_DELAYA].param_xform[id_EDGE_MONITOR] = ctx->id("DELAY.EDGE_MONITOR");
|
||||
base_iodelay_rules[id_DELAYA].param_xform[id_WAIT_FOR_EDGE] = ctx->id("DELAY.WAIT_FOR_EDGE");
|
||||
|
||||
base_iodelay_rules[id_DELAYA].port_xform[id_COARSE0] = id_CIBCRS0;
|
||||
base_iodelay_rules[id_DELAYA].port_xform[id_COARSE1] = id_CIBCRS1;
|
||||
base_iodelay_rules[id_DELAYA].port_xform[id_CFLAG] = id_COUT;
|
||||
|
||||
// Find IO delays, and convert them to IOLOGIC
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (!ci->type.in(id_DELAYA, id_DELAYB))
|
||||
continue;
|
||||
if (str_or_default(ci->params, id_DEL_MODE, "USER_DEFINED") != "USER_DEFINED") {
|
||||
// TODO: DEL_MODE (we need to work out how to convert these to a DEL_VALUE)
|
||||
log_error("DEL_MODE other than \"USER_DEFINED\" is not supported on DELAY '%s'\n", ci->name.c_str(ctx));
|
||||
}
|
||||
xform_cell(base_iodelay_rules, ci);
|
||||
|
||||
NetInfo *a = ci->getPort(id_A);
|
||||
if (a != nullptr && a->driver.cell != nullptr && a->driver.cell->type.in(id_SEIO18_CORE, id_SEIO33_CORE, id_DIFFIO18_CORE)) {
|
||||
// It's an input delay
|
||||
log_info(" processing input delay cell '%s'\n", ci->name.c_str(ctx));
|
||||
ci->params[id_INMUX] = std::string("DELAY");
|
||||
ci->renamePort(id_A, id_DI);
|
||||
ci->renamePort(id_Z, id_INDD);
|
||||
continue;
|
||||
}
|
||||
NetInfo *z = ci->getPort(id_Z);
|
||||
if (z != nullptr && z->users.entries() == 1 && (*z->users.begin()).cell->type.in(id_SEIO18_CORE, id_SEIO33_CORE, id_DIFFIO18_CORE)) {
|
||||
// It's an output delay
|
||||
log_info(" processing output delay cell '%s'\n", ci->name.c_str(ctx));
|
||||
ci->params[id_OUTMUX] = std::string("DELAY");
|
||||
ci->renamePort(id_A, id_TXDATA0);
|
||||
ci->renamePort(id_Z, id_DOUT);
|
||||
continue;
|
||||
}
|
||||
log_error("Failed to determine if delay cell '%s' was an input or output delay.\n", ci->name.c_str(ctx));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void transform_iologic()
|
||||
{
|
||||
dict<IdString, XFormRule> iol_rules;
|
||||
|
|
@ -1303,6 +1355,7 @@ struct NexusPacker
|
|||
void pack_iologic()
|
||||
{
|
||||
log_info("Packing IOLOGIC...\n");
|
||||
pack_iodelay();
|
||||
transform_iologic();
|
||||
constrain_merge_iol();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue