diff options
Diffstat (limited to 'passes')
| -rw-r--r-- | passes/memory/memory_collect.cc | 4 | ||||
| -rw-r--r-- | passes/opt/opt_share.cc | 15 | ||||
| -rw-r--r-- | passes/pmgen/xilinx_dsp.pmg | 6 | ||||
| -rw-r--r-- | passes/techmap/abc9.cc | 69 | ||||
| -rw-r--r-- | passes/techmap/clkbufmap.cc | 41 |
5 files changed, 99 insertions, 36 deletions
diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc index 6acbce62f..9dcb3f024 100644 --- a/passes/memory/memory_collect.cc +++ b/passes/memory/memory_collect.cc @@ -218,6 +218,10 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory) mem->setPort("\\RD_DATA", sig_rd_data); mem->setPort("\\RD_EN", sig_rd_en); + // Copy attributes from RTLIL memory to $mem + for (auto attr : memory->attributes) + mem->attributes[attr.first] = attr.second; + for (auto c : memcells) module->remove(c); diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index 2c456705c..f59f978a6 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -83,7 +83,9 @@ struct ExtSigSpec { bool operator==(const ExtSigSpec &other) const { return is_signed == other.is_signed && sign == other.sign && sig == other.sig && semantics == other.semantics; } }; -#define BITWISE_OPS ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_), ID($and), ID($or), ID($xor), ID($xnor) +#define FINE_BITWISE_OPS ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_) + +#define BITWISE_OPS FINE_BITWISE_OPS, ID($and), ID($or), ID($xor), ID($xnor) #define REDUCTION_OPS ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($reduce_nand) @@ -250,14 +252,19 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< shared_op->setPort(ID(CO), alu_co.extract(0, conn_width)); } - shared_op->setParam(ID(Y_WIDTH), conn_width); + bool is_fine = shared_op->type.in(FINE_BITWISE_OPS); + + if (!is_fine) + shared_op->setParam(ID(Y_WIDTH), conn_width); if (decode_port(shared_op, ID::A, &assign_map) == operand) { shared_op->setPort(ID::B, mux_to_oper); - shared_op->setParam(ID(B_WIDTH), max_width); + if (!is_fine) + shared_op->setParam(ID(B_WIDTH), max_width); } else { shared_op->setPort(ID::A, mux_to_oper); - shared_op->setParam(ID(A_WIDTH), max_width); + if (!is_fine) + shared_op->setParam(ID(A_WIDTH), max_width); } } diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 0ba529011..5d3b9c2eb 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -347,9 +347,9 @@ match postAdd index <SigBit> port(postAdd, AB)[0] === sigP[0] filter GetSize(port(postAdd, AB)) >= GetSize(sigP) filter port(postAdd, AB).extract(0, GetSize(sigP)) == sigP - // Check that remainder of AB is a sign-extension - define <bool> AB_SIGNED (param(postAdd, AB == \A ? \A_SIGNED : \B_SIGNED).as_bool()) - filter port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(AB_SIGNED ? sigP[GetSize(sigP)-1] : State::S0, GetSize(port(postAdd, AB))-GetSize(sigP)) + // Check that remainder of AB is a sign- or zero-extension + filter port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(sigP[GetSize(sigP)-1], GetSize(port(postAdd, AB))-GetSize(sigP)) || port(postAdd, AB).extract_end(GetSize(sigP)) == SigSpec(State::S0, GetSize(port(postAdd, AB))-GetSize(sigP)) + set postAddAB AB optional endmatch diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 27106cc5d..8276c3c16 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -94,20 +94,30 @@ void handle_loops(RTLIL::Design *design) if (cell->output(c.first)) { SigBit b = c.second.as_bit(); Wire *w = b.wire; - log_assert(!w->port_input); - w->port_input = true; - w = module->wire(stringf("%s.abci", w->name.c_str())); - if (!w) { - w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire)); - w->port_output = true; + if (w->port_input) { + // In this case, hopefully the loop break has been already created + // Get the non-prefixed wire + Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str())); + log_assert(wo != nullptr); + log_assert(wo->port_output); + log_assert(b.offset < GetSize(wo)); + c.second = RTLIL::SigBit(wo, b.offset); } else { - log_assert(w->port_input); - log_assert(b.offset < GetSize(w)); + // Create a new output/input loop break + w->port_input = true; + w = module->wire(stringf("%s.abco", w->name.c_str())); + if (!w) { + w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire)); + w->port_output = true; + } + else { + log_assert(w->port_input); + log_assert(b.offset < GetSize(w)); + } + w->set_bool_attribute(ID(abc9_scc_break)); + c.second = RTLIL::SigBit(w, b.offset); } - w->set_bool_attribute(ID(abc9_scc_break)); - module->swap_names(b.wire, w); - c.second = RTLIL::SigBit(w, b.offset); } } } @@ -420,24 +430,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri design->selection_stack.pop_back(); - // Now 'unexpose' those wires by undoing - // the expose operation -- remove them from PO/PI - // and re-connecting them back together - for (auto wire : module->wires()) { - auto it = wire->attributes.find(ID(abc9_scc_break)); - if (it != wire->attributes.end()) { - wire->attributes.erase(it); - log_assert(wire->port_output); - wire->port_output = false; - RTLIL::Wire *i_wire = module->wire(wire->name.str() + ".abci"); - log_assert(i_wire); - log_assert(i_wire->port_input); - i_wire->port_input = false; - module->connect(i_wire, wire); - } - } - module->fixup_ports(); - log_header(design, "Executing ABC9.\n"); if (!lut_costs.empty()) { @@ -781,6 +773,25 @@ clone_lut: } } + // Now 'unexpose' those wires by undoing + // the expose operation -- remove them from PO/PI + // and re-connecting them back together + for (auto wire : module->wires()) { + auto it = wire->attributes.find(ID(abc9_scc_break)); + if (it != wire->attributes.end()) { + wire->attributes.erase(it); + log_assert(wire->port_output); + wire->port_output = false; + std::string name = wire->name.str(); + RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5)); + log_assert(i_wire); + log_assert(i_wire->port_input); + i_wire->port_input = false; + module->connect(i_wire, wire); + } + } + module->fixup_ports(); + //log("ABC RESULTS: internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires); log("ABC RESULTS: input signals: %8d\n", in_wires); log("ABC RESULTS: output signals: %8d\n", out_wires); diff --git a/passes/techmap/clkbufmap.cc b/passes/techmap/clkbufmap.cc index 246932d81..b9cd68883 100644 --- a/passes/techmap/clkbufmap.cc +++ b/passes/techmap/clkbufmap.cc @@ -115,6 +115,8 @@ struct ClkbufmapPass : public Pass { // Cell type, port name, bit index. pool<pair<IdString, pair<IdString, int>>> sink_ports; pool<pair<IdString, pair<IdString, int>>> buf_ports; + dict<pair<IdString, pair<IdString, int>>, pair<IdString, int>> inv_ports_out; + dict<pair<IdString, pair<IdString, int>>, pair<IdString, int>> inv_ports_in; // Process submodules before module using them. std::vector<Module *> modules_sorted; @@ -133,6 +135,14 @@ struct ClkbufmapPass : public Pass { if (wire->get_bool_attribute("\\clkbuf_sink")) for (int i = 0; i < GetSize(wire); i++) sink_ports.insert(make_pair(module->name, make_pair(wire->name, i))); + auto it = wire->attributes.find("\\clkbuf_inv"); + if (it != wire->attributes.end()) { + IdString in_name = RTLIL::escape_id(it->second.decode_string()); + for (int i = 0; i < GetSize(wire); i++) { + inv_ports_out[make_pair(module->name, make_pair(wire->name, i))] = make_pair(in_name, i); + inv_ports_in[make_pair(module->name, make_pair(in_name, i))] = make_pair(wire->name, i); + } + } } continue; } @@ -157,6 +167,37 @@ struct ClkbufmapPass : public Pass { if (buf_ports.count(make_pair(cell->type, make_pair(port.first, i)))) buf_wire_bits.insert(sigmap(port.second[i])); + // Third, propagate tags through inverters. + bool retry = true; + while (retry) { + retry = false; + for (auto cell : module->cells()) + for (auto port : cell->connections()) + for (int i = 0; i < port.second.size(); i++) { + auto it = inv_ports_out.find(make_pair(cell->type, make_pair(port.first, i))); + auto bit = sigmap(port.second[i]); + // If output of an inverter is connected to a sink, mark it as buffered, + // and request a buffer on the inverter's input instead. + if (it != inv_ports_out.end() && !buf_wire_bits.count(bit) && sink_wire_bits.count(bit)) { + buf_wire_bits.insert(bit); + auto other_bit = sigmap(cell->getPort(it->second.first)[it->second.second]); + sink_wire_bits.insert(other_bit); + retry = true; + } + // If input of an inverter is marked as already-buffered, + // mark its output already-buffered as well. + auto it2 = inv_ports_in.find(make_pair(cell->type, make_pair(port.first, i))); + if (it2 != inv_ports_in.end() && buf_wire_bits.count(bit)) { + auto other_bit = sigmap(cell->getPort(it2->second.first)[it2->second.second]); + if (!buf_wire_bits.count(other_bit)) { + buf_wire_bits.insert(other_bit); + retry = true; + } + } + + } + }; + // Collect all driven bits. for (auto cell : module->cells()) for (auto port : cell->connections()) |
