aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nexus/arch.h1
-rw-r--r--nexus/constids.inc23
-rw-r--r--nexus/fasm.cc32
-rw-r--r--nexus/global.cc11
-rw-r--r--nexus/pack.cc30
-rw-r--r--nexus/pins.cc26
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