mirror of https://github.com/YosysHQ/yosys.git
coolrunner2: twines
This commit is contained in:
parent
e56e8c3818
commit
9d41958e6a
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue