diff options
-rw-r--r-- | nexus/arch.h | 1 | ||||
-rw-r--r-- | nexus/constids.inc | 23 | ||||
-rw-r--r-- | nexus/fasm.cc | 32 | ||||
-rw-r--r-- | nexus/global.cc | 11 | ||||
-rw-r--r-- | nexus/pack.cc | 30 | ||||
-rw-r--r-- | nexus/pins.cc | 26 |
6 files changed, 121 insertions, 2 deletions
diff --git a/nexus/arch.h b/nexus/arch.h index 5dcc53bc..9dfc4551 100644 --- a/nexus/arch.h +++ b/nexus/arch.h @@ -800,6 +800,7 @@ enum CellPinStyle PINSTYLE_DEDI = 0x0000, // dedicated signals, leave alone PINSTYLE_PU = 0x4022, // signals that float high and default high PINSTYLE_PU_NONCIB = 0x0022, // signals that float high and default high + PINSTYLE_PD_NONCIB = 0x0012, // signals that float high and default low PINSTYLE_T = 0x4027, // PIO 'T' signal PINSTYLE_ADLSB = 0x4017, // special case of the EBR address MSBs diff --git a/nexus/constids.inc b/nexus/constids.inc index 08ca5d09..03b144a2 100644 --- a/nexus/constids.inc +++ b/nexus/constids.inc @@ -480,3 +480,26 @@ X(CEB2B3) X(RSTB0B1) X(RSTB2B3) X(M9ADDSUB) + +X(DPHY) +X(DPHY_CORE) +X(CKN) +X(CKP) +X(DN0) +X(DN1) +X(DN2) +X(DN3) +X(DP0) +X(DP1) +X(DP2) +X(DP3) +X(DP4) +X(SCCLKIN) +X(SCRSTNIN) +X(CLKREF) +X(U2TDE4CK) +X(U1ENTHEN) +X(U2END2) +X(U3END3) +X(UED0THEN) +X(URXCKINE) diff --git a/nexus/fasm.cc b/nexus/fasm.cc index 0b8b6377..4394aebc 100644 --- a/nexus/fasm.cc +++ b/nexus/fasm.cc @@ -569,6 +569,15 @@ struct NexusFasmWriter {"SSC_STEP_IN", 7}, {"SSC_TBASE", 12}, {"V2I_PP_ICTRL", 5}, }; + + // Which MIPI params are 'word' values + const std::unordered_map<std::string, int> dphy_word_params = { + {"CM", 8}, {"CN", 5}, {"CO", 3}, {"RSEL", 2}, {"RXCDRP", 2}, + {"RXDATAWIDTHHS", 2}, {"RXLPRP", 3}, {"TEST_ENBL", 6}, + {"TEST_PATTERN", 32}, {"TST", 4}, {"TXDATAWIDTHHS", 2}, + {"UC_PRG_RXHS_SETTLE", 6}, {"U_PRG_HS_PREPARE", 2}, + {"U_PRG_HS_TRAIL", 6}, {"U_PRG_HS_ZERO", 6}, {"U_PRG_RXHS_SETTLE", 6} + }; /* clang-format on */ // Write out config for some kind of PLL cell @@ -596,6 +605,27 @@ struct NexusFasmWriter } pop(); } + // Write out config for a DPHY_CORE cell + // TODO: duplication with PLL and other hard IP... + void write_dphy(const CellInfo *cell) + { + BelId bel = cell->bel; + push(stringf("IP_%s", ctx->nameOf(IdString(ctx->bel_data(bel).name)))); + for (auto param : sorted_cref(cell->params)) { + const std::string &name = param.first.str(ctx); + if (is_mux_param(name) || name == "GSR") + continue; + auto fnd_word = dphy_word_params.find(name); + if (fnd_word != dphy_word_params.end()) { + write_int_vector(stringf("%s[%d:0]", name.c_str(), fnd_word->second - 1), + ctx->parse_lattice_param(cell, param.first, fnd_word->second, 0).as_int64(), + fnd_word->second); + } else { + write_bit(stringf("%s.%s", name.c_str(), param.second.as_string().c_str())); + } + } + pop(); + } // Write out config for an LRAM_CORE cell void write_lram(const CellInfo *cell) { @@ -750,6 +780,8 @@ struct NexusFasmWriter write_pll(ci); else if (ci->type == id_LRAM_CORE) write_lram(ci); + else if (ci->type == id_DPHY_CORE) + write_dphy(ci); blank(); } // Write config for unused bels diff --git a/nexus/global.cc b/nexus/global.cc index 62633df9..53306e21 100644 --- a/nexus/global.cc +++ b/nexus/global.cc @@ -136,10 +136,19 @@ struct NexusGlobalRouter } } + bool is_relaxed_sink(const PortRef &sink) const + { + // This DPHY clock port can't be routed without going through some general routing + if (sink.cell->type == id_DPHY_CORE && sink.port == id_URXCKINE) + return true; + return false; + } + void route_clk_net(NetInfo *net) { for (size_t i = 0; i < net->users.size(); i++) - backwards_bfs_route(net, i, 1000000, true, [&](PipId pip) { return global_pip_filter(pip); }); + backwards_bfs_route(net, i, 1000000, true, + [&](PipId pip) { return is_relaxed_sink(net->users.at(i)) || global_pip_filter(pip); }); log_info(" routed net '%s' using global resources\n", ctx->nameOf(net)); } diff --git a/nexus/pack.cc b/nexus/pack.cc index af1a921d..ffec29bd 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -1027,7 +1027,7 @@ struct NexusPacker {id_OSCA, id_OSC_CORE}, {id_DP16K, id_DP16K_MODE}, {id_PDP16K, id_PDP16K_MODE}, {id_PDPSC16K, id_PDPSC16K_MODE}, {id_SP16K, id_SP16K_MODE}, {id_FIFO16K, id_FIFO16K_MODE}, {id_SP512K, id_SP512K_MODE}, {id_DPSC512K, id_DPSC512K_MODE}, {id_PDPSC512K, id_PDPSC512K_MODE}, - {id_PLL, id_PLL_CORE}, + {id_PLL, id_PLL_CORE}, {id_DPHY, id_DPHY_CORE}, }; for (auto cell : sorted(ctx->cells)) { @@ -1959,6 +1959,33 @@ struct NexusPacker } } + // Map LOC attribute on DPHY_CORE to a bel + // TDPHY_CORE2 is Radiant 2.0 style, DPHY0 is Radiant 2.2 + // TODO: LIFCL-17 (perhaps remove the hardcoded map) + const std::unordered_map<std::string, std::string> dphy_loc_map = { + {"TDPHY_CORE2", "X4/Y0/TDPHY_CORE2"}, + {"DPHY0", "X4/Y0/TDPHY_CORE2"}, + {"TDPHY_CORE26", "X28/Y0/TDPHY_CORE26"}, + {"DPHY1", "X28/Y0/TDPHY_CORE26"}, + }; + + void pack_ip() + { + for (auto cell : sorted(ctx->cells)) { + CellInfo *ci = cell.second; + if (ci->type == id_DPHY_CORE) { + auto loc_attr = ci->attrs.find(id_LOC); + if (loc_attr == ci->attrs.end()) + log_error("LOC attribute is required for DPHY_CORE '%s'\n", ctx->nameOf(ci)); + const std::string &loc = loc_attr->second.as_string(); + auto dphy_bel = dphy_loc_map.find(loc); + if (dphy_bel == dphy_loc_map.end()) + log_error("Invalid location '%s' for DPHY_CORE '%s'\n", loc.c_str(), ctx->nameOf(ci)); + ci->attrs[id_BEL] = dphy_bel->second; + } + } + } + explicit NexusPacker(Context *ctx) : ctx(ctx) {} void operator()() @@ -1975,6 +2002,7 @@ struct NexusPacker pack_plls(); pack_constants(); pack_luts(); + pack_ip(); promote_globals(); place_globals(); generate_constraints(); diff --git a/nexus/pins.cc b/nexus/pins.cc index 0e27214b..a283953b 100644 --- a/nexus/pins.cc +++ b/nexus/pins.cc @@ -189,6 +189,32 @@ static const std::unordered_map<IdString, Arch::CellPinsData> base_cell_pin_data {id_SCANRST, PINSTYLE_DEDI}, {id_OPCGLDCK, PINSTYLE_DEDI}, {{}, PINSTYLE_CIB}, + }}, + {id_DPHY_CORE, + { + {id_CKN, PINSTYLE_DEDI}, + {id_CKP, PINSTYLE_DEDI}, + {id_DN0, PINSTYLE_DEDI}, + {id_DN1, PINSTYLE_DEDI}, + {id_DN2, PINSTYLE_DEDI}, + {id_DN3, PINSTYLE_DEDI}, + {id_DP0, PINSTYLE_DEDI}, + {id_DP1, PINSTYLE_DEDI}, + {id_DP2, PINSTYLE_DEDI}, + {id_DP3, PINSTYLE_DEDI}, + {id_SCCLKIN, PINSTYLE_DEDI}, + {id_SCRSTNIN, PINSTYLE_DEDI}, + {id_SCANCLK, PINSTYLE_DEDI}, + {id_SCANRST, PINSTYLE_DEDI}, + {id_LMMIRESETN, PINSTYLE_DEDI}, + {id_CLKREF, PINSTYLE_DEDI}, + {id_U2TDE4CK, PINSTYLE_DEDI}, + {id_OPCGLDCK, PINSTYLE_DEDI}, + {id_U1ENTHEN, PINSTYLE_PD_NONCIB}, + {id_U2END2, PINSTYLE_PD_NONCIB}, + {id_U3END3, PINSTYLE_PD_NONCIB}, + {id_UED0THEN, PINSTYLE_PD_NONCIB}, + {{}, PINSTYLE_CIB}, }}}; } // namespace |