nexus: Support for hard DPHY

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2021-03-08 15:05:58 +00:00
parent 91064c7ec8
commit 08c7f97b1e
4 changed files with 73 additions and 2 deletions

View File

@ -481,6 +481,7 @@ X(RSTB0B1)
X(RSTB2B3)
X(M9ADDSUB)
X(DPHY)
X(DPHY_CORE)
X(CKN)
X(CKP)
@ -501,3 +502,4 @@ X(U1ENTHEN)
X(U2END2)
X(U3END3)
X(UED0THEN)
X(URXCKINE)

View File

@ -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

View File

@ -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));
}

View File

@ -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();