aboutsummaryrefslogtreecommitdiffstats
path: root/ecp5/cells.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ecp5/cells.cc')
-rw-r--r--ecp5/cells.cc56
1 files changed, 55 insertions, 1 deletions
diff --git a/ecp5/cells.cc b/ecp5/cells.cc
index 31839ee4..38bcc17c 100644
--- a/ecp5/cells.cc
+++ b/ecp5/cells.cc
@@ -41,6 +41,22 @@ std::unique_ptr<CellInfo> create_ecp5_cell(Context *ctx, IdString type, std::str
new_cell->name = ctx->id(name);
}
new_cell->type = type;
+
+ auto copy_bel_ports = [&]() {
+ // First find a Bel of the target type
+ BelId tgt;
+ for (auto bel : ctx->getBels()) {
+ if (ctx->getBelType(bel) == type) {
+ tgt = bel;
+ break;
+ }
+ }
+ NPNR_ASSERT(tgt != BelId());
+ for (auto port : ctx->getBelPins(tgt)) {
+ add_port(ctx, new_cell.get(), port.str(ctx), ctx->getBelPinType(tgt, port));
+ }
+ };
+
if (type == ctx->id("TRELLIS_SLICE")) {
new_cell->params[ctx->id("MODE")] = "LOGIC";
new_cell->params[ctx->id("GSR")] = "DISABLED";
@@ -111,11 +127,17 @@ std::unique_ptr<CellInfo> create_ecp5_cell(Context *ctx, IdString type, std::str
} else if (type == ctx->id("TRELLIS_IO")) {
new_cell->params[ctx->id("DIR")] = "INPUT";
new_cell->attrs[ctx->id("IO_TYPE")] = "LVCMOS33";
+ new_cell->params[ctx->id("DATAMUX_ODDR")] = "PADDO";
+ new_cell->params[ctx->id("DATAMUX_MDDR")] = "PADDO";
add_port(ctx, new_cell.get(), "B", PORT_INOUT);
add_port(ctx, new_cell.get(), "I", PORT_IN);
add_port(ctx, new_cell.get(), "T", PORT_IN);
add_port(ctx, new_cell.get(), "O", PORT_OUT);
+
+ add_port(ctx, new_cell.get(), "IOLDO", PORT_IN);
+ add_port(ctx, new_cell.get(), "IOLTO", PORT_IN);
+
} else if (type == ctx->id("LUT4")) {
new_cell->params[ctx->id("INIT")] = "0";
@@ -150,6 +172,38 @@ std::unique_ptr<CellInfo> create_ecp5_cell(Context *ctx, IdString type, std::str
add_port(ctx, new_cell.get(), "CLKI", PORT_IN);
add_port(ctx, new_cell.get(), "CLKO", PORT_OUT);
add_port(ctx, new_cell.get(), "CE", PORT_IN);
+ } else if (type == id_IOLOGIC || type == id_SIOLOGIC) {
+ new_cell->params[ctx->id("MODE")] = "NONE";
+ new_cell->params[ctx->id("GSR")] = "DISABLED";
+ new_cell->params[ctx->id("CLKIMUX")] = "CLK";
+ new_cell->params[ctx->id("CLKOMUX")] = "CLK";
+ new_cell->params[ctx->id("LSRIMUX")] = "0";
+ new_cell->params[ctx->id("LSROMUX")] = "0";
+ new_cell->params[ctx->id("LSRMUX")] = "LSR";
+
+ new_cell->params[ctx->id("DELAY.OUTDEL")] = "DISABLED";
+ new_cell->params[ctx->id("DELAY.DEL_VALUE")] = "0";
+ new_cell->params[ctx->id("DELAY.WAIT_FOR_EDGE")] = "DISABLED";
+
+ if (type == id_IOLOGIC) {
+ new_cell->params[ctx->id("IDDRXN.MODE")] = "NONE";
+ new_cell->params[ctx->id("ODDRXN.MODE")] = "NONE";
+
+ new_cell->params[ctx->id("MIDDRX.MODE")] = "NONE";
+ new_cell->params[ctx->id("MODDRX.MODE")] = "NONE";
+ new_cell->params[ctx->id("MTDDRX.MODE")] = "NONE";
+
+ new_cell->params[ctx->id("IOLTOMUX")] = "NONE";
+ new_cell->params[ctx->id("MTDDRX.DQSW_INVERT")] = "DISABLED";
+ new_cell->params[ctx->id("MTDDRX.REGSET")] = "RESET";
+
+ new_cell->params[ctx->id("MIDDRX_MODDRX.WRCLKMUX")] = "NONE";
+ }
+ // Just copy ports from the Bel
+ copy_bel_ports();
+ } else if (type == id_TRELLIS_ECLKBUF) {
+ add_port(ctx, new_cell.get(), "ECLKI", PORT_IN);
+ add_port(ctx, new_cell.get(), "ECLKO", PORT_OUT);
} else {
log_error("unable to create ECP5 cell of type %s", type.c_str(ctx));
}
@@ -365,7 +419,7 @@ void nxio_to_tr(Context *ctx, CellInfo *nxio, CellInfo *trio, std::vector<std::u
ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); },
ctx->id("Y"));
if (tbuf) {
- replace_port(tbuf, ctx->id("I"), trio, ctx->id("I"));
+ replace_port(tbuf, ctx->id("A"), trio, ctx->id("I"));
// Need to invert E to form T
std::unique_ptr<CellInfo> inv_lut = create_ecp5_cell(ctx, ctx->id("LUT4"), trio->name.str(ctx) + "$invert_T");
replace_port(tbuf, ctx->id("E"), inv_lut.get(), ctx->id("A"));