techlibs: rebuild attribute name handling on the pool

This commit is contained in:
Emil J. Tywoniak
2026-08-13 18:15:58 +02:00
parent b3c7a25be5
commit 72a7d9eb1f
3 changed files with 66 additions and 47 deletions
+30 -25
View File
@@ -23,6 +23,11 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
static IdString uniq(RTLIL::Module *module, std::string name)
{
return module->uniquify(std::move(name));
}
RTLIL::Wire *makexorbuffer(RTLIL::Module *module, SigBit inwire, const char *cellname)
{
RTLIL::Wire *outwire = nullptr;
@@ -31,9 +36,9 @@ RTLIL::Wire *makexorbuffer(RTLIL::Module *module, SigBit inwire, const char *cel
{
// Constant 1
outwire = module->addWire(
module->uniquify(stringf("$xc2fix$%s_BUF1_XOR_OUT", cellname)));
uniq(module, stringf("$xc2fix$%s_BUF1_XOR_OUT", cellname)));
auto xor_cell = module->addCell(
module->uniquify(stringf("$xc2fix$%s_BUF1_XOR", cellname)),
uniq(module, stringf("$xc2fix$%s_BUF1_XOR", cellname)),
ID(MACROCELL_XOR));
xor_cell->setParam(ID(INVERT_OUT), true);
xor_cell->setPort(ID(OUT), outwire);
@@ -42,9 +47,9 @@ RTLIL::Wire *makexorbuffer(RTLIL::Module *module, SigBit inwire, const char *cel
{
// Constant 0
outwire = module->addWire(
module->uniquify(stringf("$xc2fix$%s_BUF0_XOR_OUT", cellname)));
uniq(module, stringf("$xc2fix$%s_BUF0_XOR_OUT", cellname)));
auto xor_cell = module->addCell(
module->uniquify(stringf("$xc2fix$%s_BUF0_XOR", cellname)),
uniq(module, stringf("$xc2fix$%s_BUF0_XOR", cellname)),
ID(MACROCELL_XOR));
xor_cell->setParam(ID(INVERT_OUT), false);
xor_cell->setPort(ID(OUT), outwire);
@@ -54,25 +59,25 @@ RTLIL::Wire *makexorbuffer(RTLIL::Module *module, SigBit inwire, const char *cel
// x; treat as 0
log_warning("While buffering, changing x to 0 into cell %s\n", cellname);
outwire = module->addWire(
module->uniquify(stringf("$xc2fix$%s_BUF0_XOR_OUT", cellname)));
uniq(module, stringf("$xc2fix$%s_BUF0_XOR_OUT", cellname)));
auto xor_cell = module->addCell(
module->uniquify(stringf("$xc2fix$%s_BUF0_XOR", cellname)),
uniq(module, stringf("$xc2fix$%s_BUF0_XOR", cellname)),
ID(MACROCELL_XOR));
xor_cell->setParam(ID(INVERT_OUT), false);
xor_cell->setPort(ID(OUT), outwire);
}
else
{
auto inwire_name = inwire.wire->name.c_str();
auto inwire_name_s = inwire.wire->name.unescape(); auto inwire_name = inwire_name_s.c_str();
outwire = module->addWire(
module->uniquify(stringf("$xc2fix$%s_BUF_XOR_OUT", inwire_name)));
uniq(module, stringf("$xc2fix$%s_BUF_XOR_OUT", inwire_name)));
auto and_to_xor_wire = module->addWire(
module->uniquify(stringf("$xc2fix$%s_BUF_AND_OUT", inwire_name)));
uniq(module, stringf("$xc2fix$%s_BUF_AND_OUT", inwire_name)));
auto and_cell = module->addCell(
module->uniquify(stringf("$xc2fix$%s_BUF_AND", inwire_name)),
uniq(module, stringf("$xc2fix$%s_BUF_AND", inwire_name)),
ID(ANDTERM));
and_cell->setParam(ID(TRUE_INP), 1);
and_cell->setParam(ID(COMP_INP), 0);
@@ -81,7 +86,7 @@ RTLIL::Wire *makexorbuffer(RTLIL::Module *module, SigBit inwire, const char *cel
and_cell->setPort(ID(IN_B), SigSpec());
auto xor_cell = module->addCell(
module->uniquify(stringf("$xc2fix$%s_BUF_XOR", inwire_name)),
uniq(module, stringf("$xc2fix$%s_BUF_XOR", inwire_name)),
ID(MACROCELL_XOR));
xor_cell->setParam(ID(INVERT_OUT), false);
xor_cell->setPort(ID(IN_PTC), and_to_xor_wire);
@@ -93,13 +98,13 @@ RTLIL::Wire *makexorbuffer(RTLIL::Module *module, SigBit inwire, const char *cel
RTLIL::Wire *makeptermbuffer(RTLIL::Module *module, SigBit inwire)
{
auto inwire_name = inwire.wire->name.c_str();
auto inwire_name_s = inwire.wire->name.unescape(); auto inwire_name = inwire_name_s.c_str();
auto outwire = module->addWire(
module->uniquify(stringf("$xc2fix$%s_BUF_AND_OUT", inwire_name)));
uniq(module, stringf("$xc2fix$%s_BUF_AND_OUT", inwire_name)));
auto and_cell = module->addCell(
module->uniquify(stringf("$xc2fix$%s_BUF_AND", inwire_name)),
uniq(module, stringf("$xc2fix$%s_BUF_AND", inwire_name)),
ID(ANDTERM));
and_cell->setParam(ID(TRUE_INP), 1);
and_cell->setParam(ID(COMP_INP), 0);
@@ -267,9 +272,9 @@ struct Coolrunner2FixupPass : public Pass {
if (input == ibuf_out_wire)
{
log("Found IBUF %s that can be packed with FF %s (type %s)\n",
ibuf_out_wire.wire->name.c_str(),
maybe_ff_cell->name.c_str(),
maybe_ff_cell->type.c_str());
ibuf_out_wire.wire->name.unescape().c_str(),
maybe_ff_cell->name.unescape().c_str(),
maybe_ff_cell->type.str().c_str());
ibuf_out_to_packed_reg_cell[ibuf_out_wire] = maybe_ff_cell;
packed_reg_out.insert(output);
@@ -300,7 +305,7 @@ struct Coolrunner2FixupPass : public Pass {
{
log("Buffering input to \"%s\"\n", cell->name);
auto xor_to_ff_wire = makexorbuffer(module, input, cell->name.c_str());
auto xor_to_ff_wire = makexorbuffer(module, input, cell->name.unescape().c_str());
if (cell->type.in(ID(FTCP), ID(FTCP_N), ID(FTDCP)))
cell->setPort(ID::T, xor_to_ff_wire);
@@ -391,7 +396,7 @@ struct Coolrunner2FixupPass : public Pass {
{
log("Buffering input to \"%s\"\n", cell->name);
auto xor_to_io_wire = makexorbuffer(module, input, cell->name.c_str());
auto xor_to_io_wire = makexorbuffer(module, input, cell->name.unescape().c_str());
cell->setPort(ID::I, xor_to_io_wire);
}
@@ -448,9 +453,9 @@ struct Coolrunner2FixupPass : public Pass {
if (xor_fanout_once[wire_in])
{
log("Additional fanout found for %s into %s (type %s), duplicating\n",
xor_cell->name.c_str(),
cell->name.c_str(),
cell->type.c_str());
xor_cell->name.unescape().c_str(),
cell->name.unescape().c_str(),
cell->type.str().c_str());
auto new_xor_cell = module->addCell(
module->uniquify(xor_cell->name), xor_cell);
@@ -496,9 +501,9 @@ struct Coolrunner2FixupPass : public Pass {
if (or_fanout_once[wire_in])
{
log("Additional fanout found for %s into %s (type %s), duplicating\n",
or_cell->name.c_str(),
cell->name.c_str(),
cell->type.c_str());
or_cell->name.unescape().c_str(),
cell->name.unescape().c_str(),
cell->type.str().c_str());
auto new_or_cell = module->addCell(
module->uniquify(or_cell->name), or_cell);
+16 -9
View File
@@ -117,37 +117,44 @@ static void run_ice40_opts(Module *module)
if (GetSize(replacement_output)) {
optimized_co.insert(sigmap(cell->getPort(ID::CO)[0]));
auto it = cell->attributes.find(IdString{"\\SB_LUT4.name"});
TwinePool &twines = module->design->twines;
IdString lut_name_attr = twines.add(std::string("\\SB_LUT4.name"));
auto it = cell->attributes.find(lut_name_attr);
if (it != cell->attributes.end()) {
module->rename(cell, it->second.decode_string());
decltype(Cell::attributes) new_attr;
for (const auto &a : cell->attributes)
if (a.first.begins_with("\\SB_LUT4.\\"))
new_attr[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second;
for (const auto &a : cell->attributes) {
std::string aname = twines.str(a.first);
if (aname.starts_with("\\SB_LUT4.\\"))
new_attr[twines.add(aname.substr(strlen("\\SB_LUT4.")))] = a.second;
else if (a.first == ID::src)
new_attr.insert(std::make_pair(a.first, a.second));
else if (a.first.in(IdString{"\\SB_LUT4.name"}, ID::keep, ID::module_not_derived))
else if (a.first.in(lut_name_attr, ID::keep, ID::module_not_derived))
continue;
else if (a.first.begins_with("\\SB_CARRY.\\"))
else if (aname.starts_with("\\SB_CARRY.\\"))
continue;
else
log_abort();
}
cell->attributes = std::move(new_attr);
}
module->connect(cell->getPort(ID::CO)[0], replacement_output);
module->design->scratchpad_set_bool("opt.did_something", true);
log("Optimized $__ICE40_CARRY_WRAPPER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n",
module, cell, log_signal(replacement_output));
cell->type = ID($lut);
auto I3 = get_bit_or_zero(cell->getPort(cell->getParam(ID(I3_IS_CI)).as_bool() ? ID::CI : ID(I3)));
cell->setPort(ID::A, { I3, inbit[1], inbit[0], get_bit_or_zero(cell->getPort(ID(I0))) });
cell->setPort(ID::Y, cell->getPort(ID::O));
RTLIL::SigSpec sig_a { I3, inbit[1], inbit[0], get_bit_or_zero(cell->getPort(ID(I0))) };
RTLIL::SigSpec sig_y = cell->getPort(ID::O);
cell->unsetPort(ID::A);
cell->unsetPort(ID::B);
cell->unsetPort(ID::CI);
cell->unsetPort(ID(I0));
cell->unsetPort(ID(I3));
cell->unsetPort(ID::CO);
cell->unsetPort(ID::O);
cell->type = ID($lut);
cell->setPort(ID::A, std::move(sig_a));
cell->setPort(ID::Y, std::move(sig_y));
cell->setParam(ID::WIDTH, 4);
cell->unsetParam(ID(I3_IS_CI));
}
+20 -13
View File
@@ -58,11 +58,12 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm)
cell->setPort(ID::O, st.lut->getPort(ID::O));
cell->setParam(ID::LUT, st.lut->getParam(ID(LUT_INIT)));
TwinePool &twines = cell->module->design->twines;
for (const auto &a : st.carry->attributes)
cell->attributes[stringf("\\SB_CARRY.%s", a.first)] = a.second;
cell->attributes[twines.add(stringf("\\SB_CARRY.%s", twines.str(a.first)))] = a.second;
for (const auto &a : st.lut->attributes)
cell->attributes[stringf("\\SB_LUT4.%s", a.first)] = a.second;
cell->attributes[IdString{"\\SB_LUT4.name"}] = Const(st.lut->name.str());
cell->attributes[twines.add(stringf("\\SB_LUT4.%s", twines.str(a.first)))] = a.second;
cell->attributes[twines.add(std::string("\\SB_LUT4.name"))] = Const(st.lut->name.str());
if (st.carry->get_bool_attribute(ID::keep) || st.lut->get_bool_attribute(ID::keep))
cell->attributes[ID::keep] = true;
@@ -109,9 +110,9 @@ struct Ice40WrapCarryPass : public Pass {
extra_args(args, argidx, design);
for (auto module : design->selected_modules()) {
if (!unwrap)
if (!unwrap) {
ice40_wrapcarry_pm(module, module->selected_cells()).run_ice40_wrapcarry(create_ice40_wrapcarry);
else {
} else {
for (auto cell : module->selected_cells()) {
if (cell->type != ID($__ICE40_CARRY_WRAPPER))
continue;
@@ -122,8 +123,12 @@ struct Ice40WrapCarryPass : public Pass {
carry->setPort(ID::CI, cell->getPort(ID::CI));
carry->setPort(ID::CO, cell->getPort(ID::CO));
module->swap_names(carry, cell);
auto lut_name = cell->attributes.at(IdString{"\\SB_LUT4.name"}, Const(NEW_ID.str())).decode_string();
auto lut = module->addCell(lut_name, ID($lut));
TwinePool &twines = module->design->twines;
IdString lut_name_attr = twines.add(std::string("\\SB_LUT4.name"));
auto lut_name = cell->attributes.find(lut_name_attr);
auto lut = lut_name != cell->attributes.end()
? module->addCell(lut_name->second.decode_string(), ID($lut))
: module->addCell(NEW_ID, ID($lut));
lut->setParam(ID::WIDTH, 4);
lut->setParam(ID::LUT, cell->getParam(ID::LUT));
auto I3 = cell->getPort(cell->getParam(ID(I3_IS_CI)).as_bool() ? ID::CI : ID(I3));
@@ -131,17 +136,19 @@ struct Ice40WrapCarryPass : public Pass {
lut->setPort(ID::Y, cell->getPort(ID::O));
Const src;
for (const auto &a : cell->attributes)
if (a.first.begins_with("\\SB_CARRY.\\"))
carry->attributes[a.first.c_str() + strlen("\\SB_CARRY.")] = a.second;
else if (a.first.begins_with("\\SB_LUT4.\\"))
lut->attributes[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second;
for (const auto &a : cell->attributes) {
std::string aname = twines.str(a.first);
if (aname.starts_with("\\SB_CARRY.\\"))
carry->attributes[twines.add(aname.substr(strlen("\\SB_CARRY.")))] = a.second;
else if (aname.starts_with("\\SB_LUT4.\\"))
lut->attributes[twines.add(aname.substr(strlen("\\SB_LUT4.")))] = a.second;
else if (a.first == ID::src)
src = a.second;
else if (a.first.in(IdString{"\\SB_LUT4.name"}, ID::keep, ID::module_not_derived, ID::src))
else if (a.first.in(lut_name_attr, ID::keep, ID::module_not_derived))
continue;
else
log_abort();
}
if (!src.empty()) {
carry->attributes.insert(std::make_pair(ID::src, src));