nexus: LUT permutation support
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
d9a71083e1
commit
502fcff765
@ -1030,7 +1030,7 @@ const std::vector<std::string> Arch::availablePlacers = {"sa",
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::string Arch::defaultRouter = "router2";
|
const std::string Arch::defaultRouter = "router1";
|
||||||
const std::vector<std::string> Arch::availableRouters = {"router1", "router2"};
|
const std::vector<std::string> Arch::availableRouters = {"router1", "router2"};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
31
nexus/arch.h
31
nexus/arch.h
@ -86,6 +86,7 @@ NPNR_PACKED_STRUCT(struct LocWireInfoPOD {
|
|||||||
enum PipFlags
|
enum PipFlags
|
||||||
{
|
{
|
||||||
PIP_FIXED_CONN = 0x8000,
|
PIP_FIXED_CONN = 0x8000,
|
||||||
|
PIP_LUT_PERM = 0x4000,
|
||||||
};
|
};
|
||||||
|
|
||||||
NPNR_PACKED_STRUCT(struct PipInfoPOD {
|
NPNR_PACKED_STRUCT(struct PipInfoPOD {
|
||||||
@ -979,10 +980,38 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
return tileStatus[bel.tile].boundcells[bel.index] == nullptr;
|
return tileStatus[bel.tile].boundcells[bel.index] == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_pseudo_pip_disabled(PipId pip) const
|
||||||
|
{
|
||||||
|
const auto &data = pip_data(pip);
|
||||||
|
if (data.flags & PIP_LUT_PERM) {
|
||||||
|
int lut_idx = (data.flags >> 8) & 0xF;
|
||||||
|
int from_pin = (data.flags >> 4) & 0xF;
|
||||||
|
int to_pin = (data.flags >> 0) & 0xF;
|
||||||
|
auto &ts = tileStatus.at(pip.tile);
|
||||||
|
if (!ts.lts)
|
||||||
|
return false;
|
||||||
|
const CellInfo *lut = ts.lts->cells[((lut_idx / 2) << 3) | (BEL_LUT0 + (lut_idx % 2))];
|
||||||
|
if (lut) {
|
||||||
|
if (lut->lutInfo.is_memory)
|
||||||
|
return true;
|
||||||
|
if (lut->lutInfo.is_carry && (from_pin == 3 || to_pin == 3))
|
||||||
|
return true; // Upper pin is special for carries
|
||||||
|
}
|
||||||
|
if (lut_idx == 4 || lut_idx == 5) {
|
||||||
|
const CellInfo *ramw = ts.lts->cells[((lut_idx / 2) << 3) | BEL_RAMW];
|
||||||
|
if (ramw)
|
||||||
|
return true; // Don't permute RAM write address
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool checkPipAvail(PipId pip) const override
|
bool checkPipAvail(PipId pip) const override
|
||||||
{
|
{
|
||||||
if (disabled_pips.count(pip))
|
if (disabled_pips.count(pip))
|
||||||
return false;
|
return false;
|
||||||
|
if (is_pseudo_pip_disabled(pip))
|
||||||
|
return false;
|
||||||
return BaseArch::checkPipAvail(pip);
|
return BaseArch::checkPipAvail(pip);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -990,6 +1019,8 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
{
|
{
|
||||||
if (disabled_pips.count(pip))
|
if (disabled_pips.count(pip))
|
||||||
return false;
|
return false;
|
||||||
|
if (is_pseudo_pip_disabled(pip))
|
||||||
|
return false;
|
||||||
return BaseArch::checkPipAvailForNet(pip, net);
|
return BaseArch::checkPipAvailForNet(pip, net);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
10
|
11
|
||||||
|
@ -207,7 +207,7 @@ struct NexusFasmWriter
|
|||||||
void write_pip(PipId pip)
|
void write_pip(PipId pip)
|
||||||
{
|
{
|
||||||
auto &pd = ctx->pip_data(pip);
|
auto &pd = ctx->pip_data(pip);
|
||||||
if (pd.flags & PIP_FIXED_CONN)
|
if ((pd.flags & PIP_FIXED_CONN) || (pd.flags & PIP_LUT_PERM))
|
||||||
return;
|
return;
|
||||||
std::string tile = tile_name(pip.tile, tile_by_type_and_loc(pip.tile, IdString(pd.tile_type)));
|
std::string tile = tile_name(pip.tile, tile_by_type_and_loc(pip.tile, IdString(pd.tile_type)));
|
||||||
std::string source_wire = escape_name(ctx->pip_src_wire_name(pip).str(ctx));
|
std::string source_wire = escape_name(ctx->pip_src_wire_name(pip).str(ctx));
|
||||||
@ -317,6 +317,43 @@ struct NexusFasmWriter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned permute_init(const CellInfo *cell)
|
||||||
|
{
|
||||||
|
unsigned orig_init = int_or_default(cell->params, id_INIT, 0);
|
||||||
|
std::array<std::vector<unsigned>, 4> phys_to_log;
|
||||||
|
const std::array<IdString, 4> ports{id_A, id_B, id_C, id_D};
|
||||||
|
for (unsigned i = 0; i < 4; i++) {
|
||||||
|
WireId pin_wire = ctx->getBelPinWire(cell->bel, ports[i]);
|
||||||
|
for (PipId pip : ctx->getPipsUphill(pin_wire)) {
|
||||||
|
if (!ctx->getBoundPipNet(pip))
|
||||||
|
continue;
|
||||||
|
const auto &data = ctx->pip_data(pip);
|
||||||
|
if (data.flags & PIP_FIXED_CONN) { // non-permuting
|
||||||
|
phys_to_log[i].push_back(i);
|
||||||
|
} else { // permuting
|
||||||
|
NPNR_ASSERT(data.flags & PIP_LUT_PERM);
|
||||||
|
unsigned from_pin = (data.flags >> 4) & 0xF;
|
||||||
|
unsigned to_pin = (data.flags >> 0) & 0xF;
|
||||||
|
NPNR_ASSERT(to_pin == i);
|
||||||
|
phys_to_log[from_pin].push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsigned permuted_init = 0;
|
||||||
|
for (unsigned i = 0; i < 16; i++) {
|
||||||
|
unsigned log_idx = 0;
|
||||||
|
for (unsigned j = 0; j < 4; j++) {
|
||||||
|
if ((i >> j) & 0x1) {
|
||||||
|
for (auto log_pin : phys_to_log[j])
|
||||||
|
log_idx |= (1 << log_pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((orig_init >> log_idx) & 0x1)
|
||||||
|
permuted_init |= (1 << i);
|
||||||
|
}
|
||||||
|
return permuted_init;
|
||||||
|
}
|
||||||
|
|
||||||
// Write config for an OXIDE_COMB cell
|
// Write config for an OXIDE_COMB cell
|
||||||
void write_comb(const CellInfo *cell)
|
void write_comb(const CellInfo *cell)
|
||||||
{
|
{
|
||||||
@ -327,7 +364,7 @@ struct NexusFasmWriter
|
|||||||
push_tile(bel.tile, id_PLC);
|
push_tile(bel.tile, id_PLC);
|
||||||
push(stringf("SLICE%c", slice));
|
push(stringf("SLICE%c", slice));
|
||||||
if (cell->params.count(id_INIT))
|
if (cell->params.count(id_INIT))
|
||||||
write_int_vector(stringf("K%d.INIT[15:0]", k), int_or_default(cell->params, id_INIT, 0), 16);
|
write_int_vector(stringf("K%d.INIT[15:0]", k), permute_init(cell), 16);
|
||||||
if (cell->lutInfo.is_carry) {
|
if (cell->lutInfo.is_carry) {
|
||||||
write_bit("MODE.CCU2");
|
write_bit("MODE.CCU2");
|
||||||
write_enum(cell, "CCU2.INJECT", "NO");
|
write_enum(cell, "CCU2.INJECT", "NO");
|
||||||
|
Loading…
Reference in New Issue
Block a user