From 9d41958e6a6c051b5f5cf809fd0afb24439f9334 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 24 Jun 2026 11:52:53 +0200 Subject: [PATCH] coolrunner2: twines --- techlibs/coolrunner2/coolrunner2_fixup.cc | 89 ++++++++++++----------- techlibs/coolrunner2/coolrunner2_sop.cc | 64 ++++++++-------- 2 files changed, 79 insertions(+), 74 deletions(-) diff --git a/techlibs/coolrunner2/coolrunner2_fixup.cc b/techlibs/coolrunner2/coolrunner2_fixup.cc index 757c91b0e..cbe9bff3e 100644 --- a/techlibs/coolrunner2/coolrunner2_fixup.cc +++ b/techlibs/coolrunner2/coolrunner2_fixup.cc @@ -23,6 +23,11 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +static TwineRef uniq(RTLIL::Module *module, std::string name) +{ + return module->uniquify(module->design->twines.add(std::move(name))); +} + RTLIL::Wire *makexorbuffer(RTLIL::Module *module, SigBit inwire, const char *cellname) { RTLIL::Wire *outwire = nullptr; @@ -31,10 +36,10 @@ 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)), - ID(MACROCELL_XOR)); + uniq(module, stringf("$xc2fix$%s_BUF1_XOR", cellname)), + TW::MACROCELL_XOR); xor_cell->setParam(ID(INVERT_OUT), true); xor_cell->setPort(TW::OUT, outwire); } @@ -42,10 +47,10 @@ 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)), - ID(MACROCELL_XOR)); + uniq(module, stringf("$xc2fix$%s_BUF0_XOR", cellname)), + TW::MACROCELL_XOR); xor_cell->setParam(ID(INVERT_OUT), false); xor_cell->setPort(TW::OUT, outwire); } @@ -54,26 +59,26 @@ 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)), - ID(MACROCELL_XOR)); + uniq(module, stringf("$xc2fix$%s_BUF0_XOR", cellname)), + TW::MACROCELL_XOR); xor_cell->setParam(ID(INVERT_OUT), false); xor_cell->setPort(TW::OUT, outwire); } else { - auto inwire_name = inwire.wire->name.c_str(); + auto inwire_name_s = inwire.wire->name.str(); 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)), - ID(ANDTERM)); + uniq(module, stringf("$xc2fix$%s_BUF_AND", inwire_name)), + TW::ANDTERM); and_cell->setParam(ID(TRUE_INP), 1); and_cell->setParam(ID(COMP_INP), 0); and_cell->setPort(TW::OUT, and_to_xor_wire); @@ -81,8 +86,8 @@ RTLIL::Wire *makexorbuffer(RTLIL::Module *module, SigBit inwire, const char *cel and_cell->setPort(TW::IN_B, SigSpec()); auto xor_cell = module->addCell( - module->uniquify(stringf("$xc2fix$%s_BUF_XOR", inwire_name)), - ID(MACROCELL_XOR)); + uniq(module, stringf("$xc2fix$%s_BUF_XOR", inwire_name)), + TW::MACROCELL_XOR); xor_cell->setParam(ID(INVERT_OUT), false); xor_cell->setPort(TW::IN_PTC, and_to_xor_wire); xor_cell->setPort(TW::OUT, outwire); @@ -93,14 +98,14 @@ 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.str(); 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)), - ID(ANDTERM)); + uniq(module, stringf("$xc2fix$%s_BUF_AND", inwire_name)), + TW::ANDTERM); and_cell->setParam(ID(TRUE_INP), 1); and_cell->setParam(ID(COMP_INP), 0); and_cell->setPort(TW::OUT, outwire); @@ -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, - maybe_ff_cell->name, - maybe_ff_cell->type); + ibuf_out_wire.wire->name.str().c_str(), + maybe_ff_cell->name.str().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); @@ -298,9 +303,9 @@ struct Coolrunner2FixupPass : public Pass { if ((!sig_fed_by_xor[input] && !sig_fed_by_io[input]) || (sig_fed_by_io[input] && ibuf_out_to_packed_reg_cell[input] != cell)) { - log("Buffering input to \"%s\"\n", cell->name); + log("Buffering input to \"%s\"\n", cell->name.str().c_str()); - auto xor_to_ff_wire = makexorbuffer(module, input, cell->name.c_str()); + auto xor_to_ff_wire = makexorbuffer(module, input, cell->name.str().c_str()); if (cell->type.in(ID(FTCP), ID(FTCP_N), ID(FTDCP))) cell->setPort(TW::T, xor_to_ff_wire); @@ -320,7 +325,7 @@ struct Coolrunner2FixupPass : public Pass { if (!sig_fed_by_pterm[clock] && !sig_fed_by_bufg[clock]) { - log("Buffering clock to \"%s\"\n", cell->name); + log("Buffering clock to \"%s\"\n", cell->name.str().c_str()); auto pterm_to_ff_wire = makeptermbuffer(module, clock); @@ -338,7 +343,7 @@ struct Coolrunner2FixupPass : public Pass { { if (!sig_fed_by_pterm[set] && !sig_fed_by_bufgsr[set]) { - log("Buffering set to \"%s\"\n", cell->name); + log("Buffering set to \"%s\"\n", cell->name.str().c_str()); auto pterm_to_ff_wire = makeptermbuffer(module, set); @@ -352,7 +357,7 @@ struct Coolrunner2FixupPass : public Pass { { if (!sig_fed_by_pterm[reset] && !sig_fed_by_bufgsr[reset]) { - log("Buffering reset to \"%s\"\n", cell->name); + log("Buffering reset to \"%s\"\n", cell->name.str().c_str()); auto pterm_to_ff_wire = makeptermbuffer(module, reset); @@ -369,7 +374,7 @@ struct Coolrunner2FixupPass : public Pass { ce = sigmap(cell->getPort(TW::CE)[0]); if (!sig_fed_by_pterm[ce]) { - log("Buffering clock enable to \"%s\"\n", cell->name); + log("Buffering clock enable to \"%s\"\n", cell->name.str().c_str()); auto pterm_to_ff_wire = makeptermbuffer(module, ce); @@ -389,9 +394,9 @@ struct Coolrunner2FixupPass : public Pass { if ((!sig_fed_by_xor[input] && !sig_fed_by_ff[input]) || packed_reg_out[input]) { - log("Buffering input to \"%s\"\n", cell->name); + log("Buffering input to \"%s\"\n", cell->name.str().c_str()); - auto xor_to_io_wire = makexorbuffer(module, input, cell->name.c_str()); + auto xor_to_io_wire = makexorbuffer(module, input, cell->name.str().c_str()); cell->setPort(TW::I, xor_to_io_wire); } @@ -404,7 +409,7 @@ struct Coolrunner2FixupPass : public Pass { oe = sigmap(cell->getPort(TW::E)[0]); if (!sig_fed_by_pterm[oe] && !sig_fed_by_bufgts[oe]) { - log("Buffering output enable to \"%s\"\n", cell->name); + log("Buffering output enable to \"%s\"\n", cell->name.str().c_str()); auto pterm_to_oe_wire = makeptermbuffer(module, oe); @@ -448,14 +453,14 @@ 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, - cell->name, - cell->type); + xor_cell->name.str().c_str(), + cell->name.str().c_str(), + cell->type.str().c_str()); auto new_xor_cell = module->addCell( - module->uniquify(xor_cell->name), xor_cell); + module->uniquify(xor_cell->name.ref()), xor_cell); auto new_wire = module->addWire( - module->uniquify(wire_in.wire->name)); + module->uniquify(wire_in.wire->name.ref())); new_xor_cell->setPort(TW::OUT, new_wire); cell->setPort(conn.first, new_wire); } @@ -496,14 +501,14 @@ 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.str().c_str(), + cell->name.str().c_str(), + cell->type.str().c_str()); auto new_or_cell = module->addCell( - module->uniquify(or_cell->name), or_cell); + module->uniquify(or_cell->name.ref()), or_cell); auto new_wire = module->addWire( - module->uniquify(wire_in.wire->name)); + module->uniquify(wire_in.wire->name.ref())); new_or_cell->setPort(TW::OUT, new_wire); cell->setPort(conn.first, new_wire); } diff --git a/techlibs/coolrunner2/coolrunner2_sop.cc b/techlibs/coolrunner2/coolrunner2_sop.cc index 298ecefd8..d871c0634 100644 --- a/techlibs/coolrunner2/coolrunner2_sop.cc +++ b/techlibs/coolrunner2/coolrunner2_sop.cc @@ -7,7 +7,7 @@ * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVTWED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES @@ -56,29 +56,29 @@ struct Coolrunner2SopPass : public Pass { } // Find wires that need to become special product terms - dict>> special_pterms_no_inv; - dict>> special_pterms_inv; + dict>> special_pterms_no_inv; + dict>> special_pterms_inv; for (auto cell : module->selected_cells()) { - if (cell->type.in(ID(FDCP), ID(FDCP_N), ID(FDDCP), ID(FTCP), ID(FTCP_N), ID(FTDCP), - ID(FDCPE), ID(FDCPE_N), ID(FDDCPE), ID(LDCP), ID(LDCP_N))) + if (cell->type.in(TW::FDCP, TW::FDCP_N, TW::FDDCP, TW::FTCP, TW::FTCP_N, TW::FTDCP, + TW::FDCPE, TW::FDCPE_N, TW::FDDCPE, TW::LDCP, TW::LDCP_N)) { if (cell->hasPort(TW::PRE)) special_pterms_no_inv[sigmap(cell->getPort(TW::PRE)[0])].insert( - make_tuple(cell, ID(PRE))); + make_tuple(cell, TW::PRE)); if (cell->hasPort(TW::CLR)) special_pterms_no_inv[sigmap(cell->getPort(TW::CLR)[0])].insert( - make_tuple(cell, ID::CLR)); + make_tuple(cell, TW::CLR)); if (cell->hasPort(TW::CE)) special_pterms_no_inv[sigmap(cell->getPort(TW::CE)[0])].insert( - make_tuple(cell, ID(CE))); + make_tuple(cell, TW::CE)); if (cell->hasPort(TW::C)) special_pterms_inv[sigmap(cell->getPort(TW::C)[0])].insert( - make_tuple(cell, ID::C)); + make_tuple(cell, TW::C)); if (cell->hasPort(TW::G)) special_pterms_inv[sigmap(cell->getPort(TW::G)[0])].insert( - make_tuple(cell, ID::G)); + make_tuple(cell, TW::G)); } } @@ -90,11 +90,11 @@ struct Coolrunner2SopPass : public Pass { // Read the inputs/outputs/parameters of the $sop cell auto sop_inputs = sigmap(cell->getPort(TW::A)); auto sop_output = sigmap(cell->getPort(TW::Y))[0]; - auto sop_depth = cell->getParam(ID::DEPTH).as_int(); - auto sop_width = cell->getParam(ID::WIDTH).as_int(); - auto sop_table = cell->getParam(ID::TABLE); + auto sop_depth = cell->getParam(ID(DEPTH)).as_int(); + auto sop_width = cell->getParam(ID(WIDTH)).as_int(); + auto sop_table = cell->getParam(ID(TABLE)); - auto sop_output_wire_name = sop_output.wire->name.c_str(); + auto sop_output_wire_name = sop_output.wire->name.str(); // Check for a $_NOT_ at the output bool has_invert = false; @@ -118,7 +118,7 @@ struct Coolrunner2SopPass : public Pass { for (int i = 0; i < sop_depth; i++) { // Wire for the output auto and_out = module->addWire( - module->uniquify(stringf("$xc2sop$%s_AND%d_OUT", sop_output_wire_name, i))); + module->uniquify(design->twines.add(stringf("$xc2sop$%s_AND%d_OUT", sop_output_wire_name, i)))); intermed_wires.insert(and_out); // Signals for the inputs @@ -138,8 +138,8 @@ struct Coolrunner2SopPass : public Pass { // Construct the cell auto and_cell = module->addCell( - module->uniquify(stringf("$xc2sop$%s_AND%d", sop_output_wire_name, i)), - ID(ANDTERM)); + module->uniquify(design->twines.add(stringf("$xc2sop$%s_AND%d", sop_output_wire_name, i))), + TW::ANDTERM); and_cell->setParam(ID(TRUE_INP), GetSize(and_in_true)); and_cell->setParam(ID(COMP_INP), GetSize(and_in_comp)); and_cell->setPort(TW::OUT, and_out); @@ -151,8 +151,8 @@ struct Coolrunner2SopPass : public Pass { { // If there is only one term, don't construct an OR cell. Directly construct the XOR gate auto xor_cell = module->addCell( - module->uniquify(stringf("$xc2sop$%s_XOR", sop_output_wire_name)), - ID(MACROCELL_XOR)); + module->uniquify(design->twines.add(stringf("$xc2sop$%s_XOR", sop_output_wire_name))), + TW::MACROCELL_XOR); xor_cell->setParam(ID(INVERT_OUT), has_invert); xor_cell->setPort(TW::IN_PTC, *intermed_wires.begin()); xor_cell->setPort(TW::OUT, sop_output); @@ -170,14 +170,14 @@ struct Coolrunner2SopPass : public Pass { if (has_invert) { auto cell = std::get<0>(x); - if (cell->type == ID(FDCP)) cell->type = ID(FDCP_N); - else if (cell->type == ID(FDCP_N)) cell->type = ID(FDCP); - else if (cell->type == ID(FTCP)) cell->type = ID(FTCP_N); - else if (cell->type == ID(FTCP_N)) cell->type = ID(FTCP); - else if (cell->type == ID(FDCPE)) cell->type = ID(FDCPE_N); - else if (cell->type == ID(FDCPE_N)) cell->type = ID(FDCPE); - else if (cell->type == ID(LDCP)) cell->type = ID(LDCP_N); - else if (cell->type == ID(LDCP_N)) cell->type = ID(LDCP); + if (cell->type == TW::FDCP) cell->type_impl = TW::FDCP_N; + else if (cell->type == TW::FDCP_N) cell->type_impl = TW::FDCP; + else if (cell->type == TW::FTCP) cell->type_impl = TW::FTCP_N; + else if (cell->type == TW::FTCP_N) cell->type_impl = TW::FTCP; + else if (cell->type == TW::FDCPE) cell->type_impl = TW::FDCPE_N; + else if (cell->type == TW::FDCPE_N) cell->type_impl = TW::FDCPE; + else if (cell->type == TW::LDCP) cell->type_impl = TW::LDCP_N; + else if (cell->type == TW::LDCP_N) cell->type_impl = TW::LDCP; else log_assert(!"Internal error! Bad cell type!"); } } @@ -198,20 +198,20 @@ struct Coolrunner2SopPass : public Pass { { // Wire from OR to XOR auto or_to_xor_wire = module->addWire( - module->uniquify(stringf("$xc2sop$%s_OR_OUT", sop_output_wire_name))); + module->uniquify(design->twines.add(stringf("$xc2sop$%s_OR_OUT", sop_output_wire_name)))); // Construct the OR cell auto or_cell = module->addCell( - module->uniquify(stringf("$xc2sop$%s_OR", sop_output_wire_name)), - ID(ORTERM)); + module->uniquify(design->twines.add(stringf("$xc2sop$%s_OR", sop_output_wire_name))), + TW::ORTERM); or_cell->setParam(ID::WIDTH, sop_depth); or_cell->setPort(TW::IN, intermed_wires); or_cell->setPort(TW::OUT, or_to_xor_wire); // Construct the XOR cell auto xor_cell = module->addCell( - module->uniquify(stringf("$xc2sop$%s_XOR", sop_output_wire_name)), - ID(MACROCELL_XOR)); + module->uniquify(design->twines.add(stringf("$xc2sop$%s_XOR", sop_output_wire_name))), + TW::MACROCELL_XOR); xor_cell->setParam(ID(INVERT_OUT), has_invert); xor_cell->setPort(TW::IN_ORTERM, or_to_xor_wire); xor_cell->setPort(TW::OUT, sop_output);