From 523df7314502e2674df5287289dcf8eb204c17ac Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 5 Aug 2014 14:47:03 +0200 Subject: [PATCH] Added support for truncating of wires to wreduce pass --- kernel/modtools.h | 24 +++++++++++++++-------- kernel/rtlil.cc | 30 ++++++++++++++++++++++++++++ kernel/rtlil.h | 7 +++++++ passes/cmds/wreduce.cc | 44 ++++++++++++++++++++++++++++++++++++++---- 4 files changed, 93 insertions(+), 12 deletions(-) diff --git a/kernel/modtools.h b/kernel/modtools.h index 56bc1882d..fde59d142 100644 --- a/kernel/modtools.h +++ b/kernel/modtools.h @@ -59,14 +59,20 @@ struct ModIndex : public RTLIL::Monitor void port_add(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &sig) { - for (int i = 0; i < SIZE(sig); i++) - database[sigmap(sig[i])].ports.insert(PortInfo(cell, port, i)); + for (int i = 0; i < SIZE(sig); i++) { + RTLIL::SigBit bit = sigmap(sig[i]); + if (bit.wire) + database[bit].ports.insert(PortInfo(cell, port, i)); + } } void port_del(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &sig) { - for (int i = 0; i < SIZE(sig); i++) - database[sigmap(sig[i])].ports.erase(PortInfo(cell, port, i)); + for (int i = 0; i < SIZE(sig); i++) { + RTLIL::SigBit bit = sigmap(sig[i]); + if (bit.wire) + database[bit].ports.erase(PortInfo(cell, port, i)); + } } const SigBitInfo &info(RTLIL::SigBit bit) @@ -83,10 +89,11 @@ struct ModIndex : public RTLIL::Monitor for (auto wire : module->wires()) if (wire->port_input || wire->port_output) for (int i = 0; i < SIZE(wire); i++) { - if (wire->port_input) - database[sigmap(RTLIL::SigBit(wire, i))].is_input = true; - if (wire->port_output) - database[sigmap(RTLIL::SigBit(wire, i))].is_output = true; + RTLIL::SigBit bit = sigmap(RTLIL::SigBit(wire, i)); + if (bit.wire && wire->port_input) + database[bit].is_input = true; + if (bit.wire && wire->port_output) + database[bit].is_output = true; } for (auto cell : module->cells()) for (auto &conn : cell->connections()) @@ -137,6 +144,7 @@ struct ModIndex : public RTLIL::Monitor { if (auto_reload_module) reload_module(); + auto it = database.find(sigmap(bit)); if (it == database.end()) return nullptr; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 792474af4..8ff564515 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1071,6 +1071,36 @@ void RTLIL::Module::rename(RTLIL::IdString old_name, RTLIL::IdString new_name) log_abort(); } +void RTLIL::Module::swap_names(RTLIL::Wire *w1, RTLIL::Wire *w2) +{ + log_assert(wires_[w1->name] == w1); + log_assert(wires_[w2->name] == w2); + log_assert(refcount_wires_ == 0); + + wires_.erase(w1->name); + wires_.erase(w2->name); + + std::swap(w1->name, w2->name); + + wires_[w1->name] = w1; + wires_[w2->name] = w2; +} + +void RTLIL::Module::swap_names(RTLIL::Cell *c1, RTLIL::Cell *c2) +{ + log_assert(cells_[c1->name] == c1); + log_assert(cells_[c2->name] == c2); + log_assert(refcount_cells_ == 0); + + cells_.erase(c1->name); + cells_.erase(c2->name); + + std::swap(c1->name, c2->name); + + cells_[c1->name] = c1; + cells_[c2->name] = c2; +} + static bool fixup_ports_compare(const RTLIL::Wire *a, const RTLIL::Wire *b) { if (a->port_id && !b->port_id) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 8dfcbcaa0..8ec599417 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -590,6 +590,10 @@ public: std::vector selected_wires() const; std::vector selected_cells() const; + template bool selected(T *member) const { + return design->selected_member(name, member->name); + } + RTLIL::Wire* wire(RTLIL::IdString id) { return wires_.count(id) ? wires_.at(id) : nullptr; } RTLIL::Cell* cell(RTLIL::IdString id) { return cells_.count(id) ? cells_.at(id) : nullptr; } @@ -604,6 +608,9 @@ public: void rename(RTLIL::Cell *cell, RTLIL::IdString new_name); void rename(RTLIL::IdString old_name, RTLIL::IdString new_name); + void swap_names(RTLIL::Wire *w1, RTLIL::Wire *w2); + void swap_names(RTLIL::Cell *c1, RTLIL::Cell *c2); + RTLIL::Wire *addWire(RTLIL::IdString name, int width = 1); RTLIL::Wire *addWire(RTLIL::IdString name, const RTLIL::Wire *other); diff --git a/passes/cmds/wreduce.cc b/passes/cmds/wreduce.cc index ce24e09b2..27571eb0d 100644 --- a/passes/cmds/wreduce.cc +++ b/passes/cmds/wreduce.cc @@ -21,8 +21,6 @@ #include "kernel/sigtools.h" #include "kernel/modtools.h" -#include - USING_YOSYS_NAMESPACE using namespace RTLIL; @@ -243,6 +241,14 @@ struct WreduceWorker return did_something; } + static int count_nontrivial_wire_attrs(RTLIL::Wire *w) + { + int count = w->attributes.size(); + count -= w->attributes.count("\\src"); + count -= w->attributes.count("\\unused_bits"); + return count; + } + void run() { for (auto c : module->selected_cells()) @@ -257,7 +263,32 @@ struct WreduceWorker work_queue_cells.clear(); for (auto bit : work_queue_bits) for (auto port : mi.query_ports(bit)) - work_queue_cells.insert(port.cell); + if (module->selected(port.cell)) + work_queue_cells.insert(port.cell); + } + + for (auto w : module->selected_wires()) + { + int unused_top_bits = 0; + + if (w->port_id > 0 || count_nontrivial_wire_attrs(w) > 0) + continue; + + for (int i = SIZE(w)-1; i >= 0; i--) { + SigBit bit(w, i); + auto info = mi.query(bit); + if (info && (info->is_input || info->is_output || SIZE(info->ports) > 0)) + break; + unused_top_bits++; + } + + if (0 < unused_top_bits && unused_top_bits < SIZE(w)) { + log("Removed top %d bits (of %d) from wire %s.%s.\n", unused_top_bits, SIZE(w), log_id(module), log_id(w)); + Wire *nw = module->addWire(NEW_ID, w); + nw->width = SIZE(w) - unused_top_bits; + module->connect(nw, SigSpec(w).extract(0, SIZE(nw))); + module->swap_names(w, nw); + } } } }; @@ -270,7 +301,12 @@ struct WreducePass : public Pass { log("\n"); log(" wreduce [options] [selection]\n"); log("\n"); - log("This command reduces the word size of operations.\n"); + log("This command reduces the word size of operations. For example it will replace\n"); + log("the 32 bit adders in the following code with adders of more appropriate widths:\n"); + log("\n"); + log(" module test(input [3:0] a, b, c, output [7:0] y);\n"); + log(" assign y = a + b + c + 1;\n"); + log(" endmodule\n"); log("\n"); } virtual void execute(std::vector args, Design *design) -- 2.30.2