1
0
mirror of https://github.com/YosysHQ/nextpnr.git synced 2026-01-11 23:53:21 +00:00
This commit is contained in:
Miodrag Milanovic 2025-10-29 09:01:27 +01:00
parent a530283600
commit af62a9abbd
4 changed files with 92 additions and 0 deletions

View File

@ -87,6 +87,30 @@ struct BitstreamBackend
return invert;
}
bool need_switching(CellInfo *cell, IdString port)
{
PortRef sink;
sink.cell = cell;
sink.port = port;
NetInfo *net_info = cell->getPort(port);
if (!net_info)
return false;
WireId dst_wire = ctx->getNetinfoSinkWire(net_info, sink, 0);
WireId cursor = dst_wire;
auto it = net_info->wires.find(cursor);
PipId pip = it->second.pip;
const auto &extra_data = *uarch->pip_extra_data(pip);
if (extra_data.type == PipExtra::PIP_EXTRA_MUX && (extra_data.flags & MUX_PERMUTATION)) {
if (extra_data.value)
return true;
}
return false;
}
void update_cpe_lt(CellInfo *cell, IdString port, IdString init, dict<IdString, Property> &params, bool even)
{
unsigned init_val = int_or_default(params, init);
@ -317,6 +341,14 @@ struct BitstreamBackend
case id_CPE_RAMIO.index: {
// Update configuration bits based on signal inversion
dict<IdString, Property> params = cell.second->params;
auto update_param = [&](IdString name) {
int x = int_or_default(params, name, 0);
// when inputs exchange theier places in LUT2
// function changes so bit 1 and bit 2 exchange values
int y = x ^ (( ( (x >> 1) ^ (x >> 2) ) & 1 ) << 1)
^ (( ( (x >> 1) ^ (x >> 2) ) & 1 ) << 2);
params[name] = Property(y ,4);
};
Loc l = ctx->getBelLocation(cell.second->bel);
params.erase(id_L2T4_UPPER);
params.erase(id_MULT_INVERT);
@ -324,6 +356,13 @@ struct BitstreamBackend
int c_i2 = int_or_default(params, id_C_I2, 0);
int c_i3 = int_or_default(params, id_C_I3, 0);
int c_i4 = int_or_default(params, id_C_I4, 0);
if (cell.second->type.in(id_CPE_BRIDGE)) {
int in = int_or_default(params, id_C_SN, 0);
if (need_switching(cell.second.get(), ctx->idf("IN%d", in+1)))
params[id_C_SN] = Property(in ^ 1,3);
}
if (cell.second->type.in(id_CPE_L2T4, id_CPE_LT_L, id_CPE_LT_U)) {
if (l.z == CPE_LT_U_Z) {
update_cpe_lt(cell.second.get(), id_IN1, id_INIT_L00, params, true);
@ -337,6 +376,12 @@ struct BitstreamBackend
update_cpe_lt(cell.second.get(), id_IN3, id_INIT_L01, params, true);
update_cpe_lt(cell.second.get(), c_i4 ? id_PINX : id_IN4, id_INIT_L01, params, false);
}
if (need_switching(cell.second.get(), id_IN1) || need_switching(cell.second.get(), id_IN2)) {
update_param(id_INIT_L00);
}
if (need_switching(cell.second.get(), id_IN3) || need_switching(cell.second.get(), id_IN4)) {
update_param(id_INIT_L01);
}
}
if (l.z == CPE_LT_FULL_Z) {
if (!cell.second->type.in(id_CPE_MULT)) {
@ -359,6 +404,18 @@ struct BitstreamBackend
update_cpe_lt(cell.second.get(), id_IN7, id_INIT_L03, params, true);
update_cpe_lt(cell.second.get(), c_i4 ? id_PINX : id_IN8, id_INIT_L03, params, false);
}
if (need_switching(cell.second.get(), id_IN1) || need_switching(cell.second.get(), id_IN2)) {
update_param(id_INIT_L00);
}
if (need_switching(cell.second.get(), id_IN3) || need_switching(cell.second.get(), id_IN4)) {
update_param(id_INIT_L01);
}
if (need_switching(cell.second.get(), id_IN5) || need_switching(cell.second.get(), id_IN6)) {
update_param(id_INIT_L02);
}
if (need_switching(cell.second.get(), id_IN7) || need_switching(cell.second.get(), id_IN8)) {
update_param(id_INIT_L03);
}
}
}

View File

@ -85,6 +85,7 @@ enum MuxFlags
MUX_VISIBLE = 2,
MUX_CONFIG = 4,
MUX_ROUTING = 8,
MUX_PERMUTATION = 16,
};
enum PipExtra

View File

@ -31,6 +31,7 @@ MUX_INVERT = 1
MUX_VISIBLE = 2
MUX_CONFIG = 4
MUX_ROUTING = 8
MUX_PERMUTATION = 16
parser = argparse.ArgumentParser()
parser.add_argument("--lib", help="Project Peppercorn python database script path", type=str, required=True)
@ -310,6 +311,8 @@ def main():
plane = int(mux.name[10:12])
if mux.name == "CPE.C_SN":
mux_flags |= MUX_ROUTING
if mux.name.startswith("CPE.PERM"):
mux_flags |= MUX_PERMUTATION
pp.extra_data = PipExtraData(PIP_EXTRA_MUX, ch.strs.id(mux.name), mux.bits, mux.value, mux_flags, plane)
if type_name in new_wires:
for wire in sorted(new_wires[type_name]):

View File

@ -309,6 +309,16 @@ void GateMatePacker::repack_cpe()
if (!cell.second->params.count(id_INIT_L20))
cell.second->params[id_INIT_L20] = Property(LUT_D1, 4);
}
if (cell.second->getPort(id_IN1) && cell.second->getPort(id_IN2)) {
if (cell.second->getPort(id_IN1) == cell.second->getPort(id_IN2)) {
log_error("Used same signal for IN1 and IN2 in %s\n", cell.second->name.c_str(ctx));
}
}
if (cell.second->getPort(id_IN3) && cell.second->getPort(id_IN4)) {
if (cell.second->getPort(id_IN3) == cell.second->getPort(id_IN4)) {
log_error("Used same signal for IN3 and IN4 in %s\n", cell.second->name.c_str(ctx));
}
}
cell.second->params[id_L2T4_UPPER] = Property((l.z == CPE_LT_U_Z) ? 1 : 0, 1);
} else if (cell.second->type.in(id_CPE_LT_L)) {
BelId bel = cell.second->bel;
@ -318,6 +328,16 @@ void GateMatePacker::repack_cpe()
loc.z = CPE_LT_FULL_Z;
ctx->unbindBel(bel);
ctx->bindBel(ctx->getBelByLocation(loc), cell.second.get(), strength);
if (cell.second->getPort(id_IN1) && cell.second->getPort(id_IN2)) {
if (cell.second->getPort(id_IN1) == cell.second->getPort(id_IN2)) {
log_error("Used same signal for IN1 and IN2 in %s\n", cell.second->name.c_str(ctx));
}
}
if (cell.second->getPort(id_IN3) && cell.second->getPort(id_IN4)) {
if (cell.second->getPort(id_IN3) == cell.second->getPort(id_IN4)) {
log_error("Used same signal for IN3 and IN4 in %s\n", cell.second->name.c_str(ctx));
}
}
cell.second->renamePort(id_IN1, id_IN5);
cell.second->renamePort(id_IN2, id_IN6);
cell.second->renamePort(id_IN3, id_IN7);
@ -374,6 +394,17 @@ void GateMatePacker::repack_cpe()
upper->movePortTo(id_IN4, cell.second.get(), id_IN4);
upper->movePortTo(id_OUT, cell.second.get(), id_OUT2);
upper->movePortTo(id_CPOUT, cell.second.get(), id_CPOUT2);
if (cell.second->getPort(id_IN1) && cell.second->getPort(id_IN2)) {
if (cell.second->getPort(id_IN1) == cell.second->getPort(id_IN2)) {
log_error("Used same signal for IN1 and IN2 in %s\n", cell.second->name.c_str(ctx));
}
}
if (cell.second->getPort(id_IN3) && cell.second->getPort(id_IN4)) {
if (cell.second->getPort(id_IN3) == cell.second->getPort(id_IN4)) {
log_error("Used same signal for IN3 and IN4 in %s\n", cell.second->name.c_str(ctx));
}
}
}
// Mark for deletion