Merge pull request #613 from YosysHQ/gatecat/nexus-dphy
Add basic support for Nexus DPHY hard IP
This commit is contained in:
commit
0f17e80eef
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user