mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-13 04:28:18 +00:00
coolrunner2: Fix packed register+input buffer insertion
The register will be packed with the input buffer if and only if the input buffer doesn't have any other loads.
This commit is contained in:
parent
a6aeee4e1a
commit
a618004897
|
@ -41,6 +41,14 @@ RTLIL::Wire *makexorbuffer(RTLIL::Module *module, SigBit inwire)
|
||||||
xor_cell->setParam("\\INVERT_OUT", false);
|
xor_cell->setParam("\\INVERT_OUT", false);
|
||||||
xor_cell->setPort("\\OUT", outwire);
|
xor_cell->setPort("\\OUT", outwire);
|
||||||
}
|
}
|
||||||
|
else if (inwire == SigBit(RTLIL::State::Sx))
|
||||||
|
{
|
||||||
|
// x; treat as 0
|
||||||
|
log_warning("While buffering, changing x to 0 on wire %s\n", outwire->name.c_str());
|
||||||
|
auto xor_cell = module->addCell(NEW_ID, "\\MACROCELL_XOR");
|
||||||
|
xor_cell->setParam("\\INVERT_OUT", false);
|
||||||
|
xor_cell->setPort("\\OUT", outwire);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto and_to_xor_wire = module->addWire(NEW_ID);
|
auto and_to_xor_wire = module->addWire(NEW_ID);
|
||||||
|
@ -174,6 +182,74 @@ struct Coolrunner2FixupPass : public Pass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is used to fix the input -> FF -> output scenario
|
||||||
|
pool<SigBit> sig_fed_by_ibuf;
|
||||||
|
for (auto cell : module->selected_cells())
|
||||||
|
{
|
||||||
|
if (cell->type == "\\IBUF")
|
||||||
|
{
|
||||||
|
auto output = sigmap(cell->getPort("\\O")[0]);
|
||||||
|
sig_fed_by_ibuf.insert(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find all of the sinks for each output from an IBUF
|
||||||
|
dict<SigBit, std::pair<int, RTLIL::Cell *>> ibuf_fanouts;
|
||||||
|
for (auto cell : module->selected_cells())
|
||||||
|
{
|
||||||
|
for (auto &conn : cell->connections())
|
||||||
|
{
|
||||||
|
if (cell->input(conn.first))
|
||||||
|
{
|
||||||
|
for (auto wire_in : sigmap(conn.second))
|
||||||
|
{
|
||||||
|
if (sig_fed_by_ibuf[wire_in])
|
||||||
|
{
|
||||||
|
auto existing_count = ibuf_fanouts[wire_in].first;
|
||||||
|
ibuf_fanouts[wire_in] =
|
||||||
|
std::pair<int, RTLIL::Cell *>(existing_count + 1, cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dict<SigBit, RTLIL::Cell *> ibuf_out_to_packed_reg_cell;
|
||||||
|
pool<SigBit> packed_reg_out;
|
||||||
|
for (auto x : ibuf_fanouts)
|
||||||
|
{
|
||||||
|
auto ibuf_out_wire = x.first;
|
||||||
|
auto fanout_count = x.second.first;
|
||||||
|
auto maybe_ff_cell = x.second.second;
|
||||||
|
|
||||||
|
// The register can be packed with the IBUF only if it's
|
||||||
|
// actually a register and it's the only fanout. Otherwise,
|
||||||
|
// the pad-to-zia path has to be used up and the register
|
||||||
|
// can't be packed with the ibuf.
|
||||||
|
if (fanout_count == 1 && maybe_ff_cell->type.in(
|
||||||
|
"\\FDCP", "\\FDCP_N", "\\FDDCP", "\\LDCP", "\\LDCP_N",
|
||||||
|
"\\FTCP", "\\FTCP_N", "\\FTDCP", "\\FDCPE", "\\FDCPE_N", "\\FDDCPE"))
|
||||||
|
{
|
||||||
|
SigBit input;
|
||||||
|
if (maybe_ff_cell->type.in("\\FTCP", "\\FTCP_N", "\\FTDCP"))
|
||||||
|
input = sigmap(maybe_ff_cell->getPort("\\T")[0]);
|
||||||
|
else
|
||||||
|
input = sigmap(maybe_ff_cell->getPort("\\D")[0]);
|
||||||
|
SigBit output = sigmap(maybe_ff_cell->getPort("\\Q")[0]);
|
||||||
|
|
||||||
|
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_to_packed_reg_cell[ibuf_out_wire] = maybe_ff_cell;
|
||||||
|
packed_reg_out.insert(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto cell : module->selected_cells())
|
for (auto cell : module->selected_cells())
|
||||||
{
|
{
|
||||||
if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\LDCP", "\\LDCP_N",
|
if (cell->type.in("\\FDCP", "\\FDCP_N", "\\FDDCP", "\\LDCP", "\\LDCP_N",
|
||||||
|
@ -188,7 +264,12 @@ struct Coolrunner2FixupPass : public Pass {
|
||||||
else
|
else
|
||||||
input = sigmap(cell->getPort("\\D")[0]);
|
input = sigmap(cell->getPort("\\D")[0]);
|
||||||
|
|
||||||
if (!sig_fed_by_xor[input] && !sig_fed_by_io[input])
|
// If the input wasn't an XOR nor an IO, then a buffer
|
||||||
|
// definitely needs to be added.
|
||||||
|
// Otherwise, if it is an IO, only leave unbuffered
|
||||||
|
// if we're being packed with the IO.
|
||||||
|
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.c_str());
|
log("Buffering input to \"%s\"\n", cell->name.c_str());
|
||||||
|
|
||||||
|
@ -278,7 +359,8 @@ struct Coolrunner2FixupPass : public Pass {
|
||||||
// Buffer IOBUFE inputs. This can only be fed from an XOR or FF.
|
// Buffer IOBUFE inputs. This can only be fed from an XOR or FF.
|
||||||
SigBit input = sigmap(cell->getPort("\\I")[0]);
|
SigBit input = sigmap(cell->getPort("\\I")[0]);
|
||||||
|
|
||||||
if (!sig_fed_by_xor[input] && !sig_fed_by_ff[input])
|
if ((!sig_fed_by_xor[input] && !sig_fed_by_ff[input]) ||
|
||||||
|
packed_reg_out[input])
|
||||||
{
|
{
|
||||||
log("Buffering input to \"%s\"\n", cell->name.c_str());
|
log("Buffering input to \"%s\"\n", cell->name.c_str());
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue