coolrunner2: twines

This commit is contained in:
Emil J. Tywoniak 2026-06-24 11:52:53 +02:00
parent e56e8c3818
commit 9d41958e6a
2 changed files with 79 additions and 74 deletions

View File

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

View File

@ -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<SigBit, pool<tuple<Cell*, IdString>>> special_pterms_no_inv;
dict<SigBit, pool<tuple<Cell*, IdString>>> special_pterms_inv;
dict<SigBit, pool<tuple<Cell*, TwineRef>>> special_pterms_no_inv;
dict<SigBit, pool<tuple<Cell*, TwineRef>>> 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);