mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-13 04:28:18 +00:00
Fix writing non-whole modules, including inouts and keeps
This commit is contained in:
parent
ec0acc9f85
commit
1f96de04c9
|
@ -142,7 +142,7 @@ struct XAigerWriter
|
||||||
{
|
{
|
||||||
pool<SigBit> undriven_bits;
|
pool<SigBit> undriven_bits;
|
||||||
pool<SigBit> unused_bits;
|
pool<SigBit> unused_bits;
|
||||||
pool<SigBit> keep_bits;
|
pool<SigBit> inout_bits;
|
||||||
|
|
||||||
// promote public wires
|
// promote public wires
|
||||||
for (auto wire : module->wires())
|
for (auto wire : module->wires())
|
||||||
|
@ -154,60 +154,45 @@ struct XAigerWriter
|
||||||
if (wire->port_input)
|
if (wire->port_input)
|
||||||
sigmap.add(wire);
|
sigmap.add(wire);
|
||||||
|
|
||||||
// promote output wires
|
// promote keep wires
|
||||||
for (auto wire : module->wires())
|
for (auto wire : module->wires())
|
||||||
if (wire->port_output)
|
if (wire->get_bool_attribute(ID::keep))
|
||||||
sigmap.add(wire);
|
sigmap.add(wire);
|
||||||
|
|
||||||
for (auto wire : module->wires())
|
for (auto wire : module->wires())
|
||||||
{
|
|
||||||
bool keep = wire->attributes.count("\\keep");
|
|
||||||
|
|
||||||
for (int i = 0; i < GetSize(wire); i++)
|
for (int i = 0; i < GetSize(wire); i++)
|
||||||
{
|
{
|
||||||
SigBit wirebit(wire, i);
|
SigBit wirebit(wire, i);
|
||||||
SigBit bit = sigmap(wirebit);
|
SigBit bit = sigmap(wirebit);
|
||||||
|
|
||||||
if (bit.wire) {
|
if (bit.wire == nullptr) {
|
||||||
undriven_bits.insert(bit);
|
if (wire->port_output) {
|
||||||
unused_bits.insert(bit);
|
aig_map[wirebit] = (bit == State::S1) ? 1 : 0;
|
||||||
}
|
if (holes_mode)
|
||||||
|
output_bits.insert(wirebit);
|
||||||
if (keep) {
|
//external_bits.insert(wirebit);
|
||||||
keep_bits.insert(wirebit);
|
}
|
||||||
if (bit != wirebit)
|
|
||||||
alias_map[wirebit] = bit;
|
|
||||||
input_bits.insert(wirebit);
|
|
||||||
output_bits.insert(wirebit);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wire->port_input) {
|
undriven_bits.insert(bit);
|
||||||
if (bit != wirebit)
|
unused_bits.insert(bit);
|
||||||
alias_map[bit] = wirebit;
|
|
||||||
input_bits.insert(wirebit);
|
if (wire->port_input)
|
||||||
}
|
input_bits.insert(bit);
|
||||||
|
|
||||||
if (wire->port_output) {
|
if (wire->port_output) {
|
||||||
if (bit != RTLIL::Sx) {
|
if (bit != wirebit)
|
||||||
if (bit != wirebit)
|
alias_map[wirebit] = bit;
|
||||||
alias_map[wirebit] = bit;
|
if (holes_mode)
|
||||||
if (holes_mode)
|
output_bits.insert(wirebit);
|
||||||
output_bits.insert(wirebit);
|
|
||||||
else
|
|
||||||
external_bits.insert(wirebit);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
log_debug("Skipping PO '%s' driven by 1'bx\n", log_signal(wirebit));
|
external_bits.insert(wirebit);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cannot fold into above due to use of sigmap
|
if (wire->port_input && wire->port_output)
|
||||||
for (auto bit : input_bits)
|
inout_bits.insert(bit);
|
||||||
undriven_bits.erase(sigmap(bit));
|
}
|
||||||
for (auto bit : output_bits)
|
|
||||||
unused_bits.erase(sigmap(bit));
|
|
||||||
|
|
||||||
// TODO: Speed up toposort -- ultimately we care about
|
// TODO: Speed up toposort -- ultimately we care about
|
||||||
// box ordering, but not individual AIG cells
|
// box ordering, but not individual AIG cells
|
||||||
|
@ -307,10 +292,9 @@ struct XAigerWriter
|
||||||
if (I != b)
|
if (I != b)
|
||||||
alias_map[b] = I;
|
alias_map[b] = I;
|
||||||
output_bits.insert(b);
|
output_bits.insert(b);
|
||||||
unused_bits.erase(I);
|
|
||||||
|
|
||||||
if (!cell_known)
|
if (!cell_known)
|
||||||
keep_bits.insert(b);
|
inout_bits.insert(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -328,11 +312,10 @@ struct XAigerWriter
|
||||||
for (auto b : c.second) {
|
for (auto b : c.second) {
|
||||||
Wire *w = b.wire;
|
Wire *w = b.wire;
|
||||||
if (!w) continue;
|
if (!w) continue;
|
||||||
input_bits.insert(b);
|
|
||||||
SigBit O = sigmap(b);
|
SigBit O = sigmap(b);
|
||||||
if (O != b)
|
if (O != b)
|
||||||
alias_map[O] = b;
|
alias_map[O] = b;
|
||||||
undriven_bits.erase(O);
|
input_bits.insert(b);
|
||||||
|
|
||||||
if (arrival)
|
if (arrival)
|
||||||
arrival_times[b] = arrival;
|
arrival_times[b] = arrival;
|
||||||
|
@ -343,12 +326,6 @@ struct XAigerWriter
|
||||||
//log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
|
//log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto cell : module->cells())
|
|
||||||
if (!module->selected(cell))
|
|
||||||
for (auto &conn : cell->connections())
|
|
||||||
for (auto bit : sigmap(conn.second))
|
|
||||||
external_bits.insert(bit);
|
|
||||||
|
|
||||||
if (abc9_box_seen) {
|
if (abc9_box_seen) {
|
||||||
dict<IdString, std::pair<IdString,int>> flop_q;
|
dict<IdString, std::pair<IdString,int>> flop_q;
|
||||||
for (auto cell : flop_boxes) {
|
for (auto cell : flop_boxes) {
|
||||||
|
@ -494,8 +471,8 @@ struct XAigerWriter
|
||||||
SigBit O = sigmap(b);
|
SigBit O = sigmap(b);
|
||||||
if (O != b)
|
if (O != b)
|
||||||
alias_map[O] = b;
|
alias_map[O] = b;
|
||||||
undriven_bits.erase(O);
|
|
||||||
input_bits.erase(b);
|
input_bits.erase(b);
|
||||||
|
undriven_bits.erase(O);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -528,56 +505,70 @@ struct XAigerWriter
|
||||||
// TODO: Free memory from toposort, bit_drivers, bit_users
|
// TODO: Free memory from toposort, bit_drivers, bit_users
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto bit : input_bits) {
|
if (!holes_mode)
|
||||||
if (!output_bits.count(bit))
|
for (auto cell : module->cells())
|
||||||
|
if (!module->selected(cell))
|
||||||
|
for (auto &conn : cell->connections())
|
||||||
|
if (cell->input(conn.first))
|
||||||
|
for (auto wirebit : conn.second)
|
||||||
|
if (sigmap(wirebit).wire)
|
||||||
|
external_bits.insert(wirebit);
|
||||||
|
|
||||||
|
// For all bits consumed outside of the selected cells,
|
||||||
|
// but driven from a selected cell, then add it as
|
||||||
|
// a primary output
|
||||||
|
for (auto wirebit : external_bits) {
|
||||||
|
SigBit bit = sigmap(wirebit);
|
||||||
|
if (!bit.wire)
|
||||||
continue;
|
continue;
|
||||||
RTLIL::Wire *wire = bit.wire;
|
if (!undriven_bits.count(bit)) {
|
||||||
// If encountering an inout port, or a keep-ed wire, then create a new wire
|
if (bit != wirebit)
|
||||||
// with $inout.out suffix, make it a PO driven by the existing inout, and
|
alias_map[wirebit] = bit;
|
||||||
// inherit existing inout's drivers
|
output_bits.insert(wirebit);
|
||||||
if ((wire->port_input && wire->port_output && !undriven_bits.count(bit))
|
|
||||||
|| keep_bits.count(bit)) {
|
|
||||||
RTLIL::IdString wire_name = stringf("$%s$inout.out", wire->name.c_str());
|
|
||||||
RTLIL::Wire *new_wire = module->wire(wire_name);
|
|
||||||
if (!new_wire)
|
|
||||||
new_wire = module->addWire(wire_name, GetSize(wire));
|
|
||||||
SigBit new_bit(new_wire, bit.offset);
|
|
||||||
module->connect(new_bit, bit);
|
|
||||||
if (not_map.count(bit)) {
|
|
||||||
auto a = not_map.at(bit);
|
|
||||||
not_map[new_bit] = a;
|
|
||||||
}
|
|
||||||
else if (and_map.count(bit)) {
|
|
||||||
auto a = and_map.at(bit);
|
|
||||||
and_map[new_bit] = a;
|
|
||||||
}
|
|
||||||
else if (alias_map.count(bit)) {
|
|
||||||
auto a = alias_map.at(bit);
|
|
||||||
alias_map[new_bit] = a;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
alias_map[new_bit] = bit;
|
|
||||||
output_bits.erase(bit);
|
|
||||||
output_bits.insert(new_bit);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto bit : external_bits)
|
for (auto bit : input_bits)
|
||||||
if (!undriven_bits.count(sigmap(bit))) {
|
undriven_bits.erase(sigmap(bit));
|
||||||
output_bits.insert(bit);
|
for (auto bit : output_bits)
|
||||||
unused_bits.erase(sigmap(bit));
|
unused_bits.erase(sigmap(bit));
|
||||||
}
|
|
||||||
|
|
||||||
for (auto bit : unused_bits)
|
for (auto bit : unused_bits)
|
||||||
undriven_bits.erase(bit);
|
undriven_bits.erase(bit);
|
||||||
|
|
||||||
if (!undriven_bits.empty() && !holes_mode) {
|
// Make all undriven bits a primary input
|
||||||
//undriven_bits.sort();
|
if (!holes_mode)
|
||||||
for (auto bit : undriven_bits) {
|
for (auto bit : undriven_bits) {
|
||||||
//log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit));
|
|
||||||
input_bits.insert(bit);
|
input_bits.insert(bit);
|
||||||
|
undriven_bits.erase(bit);
|
||||||
}
|
}
|
||||||
//log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module));
|
|
||||||
|
// For inout ports, or keep-ed wires, then create a new wire with an
|
||||||
|
// $inout.out suffix, make it a PO driven by the existing inout, and
|
||||||
|
// inherit existing inout's drivers
|
||||||
|
for (auto bit : inout_bits) {
|
||||||
|
RTLIL::Wire *wire = bit.wire;
|
||||||
|
RTLIL::IdString wire_name = stringf("$%s$inout.out", wire->name.c_str());
|
||||||
|
RTLIL::Wire *new_wire = module->wire(wire_name);
|
||||||
|
if (!new_wire)
|
||||||
|
new_wire = module->addWire(wire_name, GetSize(wire));
|
||||||
|
SigBit new_bit(new_wire, bit.offset);
|
||||||
|
module->connect(new_bit, bit);
|
||||||
|
if (not_map.count(bit)) {
|
||||||
|
auto a = not_map.at(bit);
|
||||||
|
not_map[new_bit] = a;
|
||||||
|
}
|
||||||
|
else if (and_map.count(bit)) {
|
||||||
|
auto a = and_map.at(bit);
|
||||||
|
and_map[new_bit] = a;
|
||||||
|
}
|
||||||
|
else if (alias_map.count(bit)) {
|
||||||
|
auto a = alias_map.at(bit);
|
||||||
|
alias_map[new_bit] = a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
alias_map[new_bit] = bit;
|
||||||
|
output_bits.erase(bit);
|
||||||
|
output_bits.insert(new_bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (holes_mode) {
|
if (holes_mode) {
|
||||||
|
@ -880,7 +871,7 @@ struct XAigerWriter
|
||||||
for (auto it = holes_module->cells_.begin(); it != holes_module->cells_.end(); ) {
|
for (auto it = holes_module->cells_.begin(); it != holes_module->cells_.end(); ) {
|
||||||
auto cell = it->second;
|
auto cell = it->second;
|
||||||
if (cell->type.in("$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
|
if (cell->type.in("$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
|
||||||
"$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1", "$_DFF_PP0_", "$_DFF_PP1_")) {
|
"$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1", "$_DFF_PP0_", "$_DFF_PP1_")) {
|
||||||
SigBit D = cell->getPort("\\D");
|
SigBit D = cell->getPort("\\D");
|
||||||
SigBit Q = cell->getPort("\\Q");
|
SigBit Q = cell->getPort("\\Q");
|
||||||
// Remove the DFF cell from what needs to be a combinatorial box
|
// Remove the DFF cell from what needs to be a combinatorial box
|
||||||
|
|
Loading…
Reference in a new issue