Added support for truncating of wires to wreduce pass
authorClifford Wolf <clifford@clifford.at>
Tue, 5 Aug 2014 12:47:03 +0000 (14:47 +0200)
committerClifford Wolf <clifford@clifford.at>
Tue, 5 Aug 2014 12:47:03 +0000 (14:47 +0200)
kernel/modtools.h
kernel/rtlil.cc
kernel/rtlil.h
passes/cmds/wreduce.cc

index 56bc1882dbc5549b6057c0fae2b78c620b98d389..fde59d1421d0612d2a3b2f4960d5a3d5f3b9dee4 100644 (file)
@@ -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;
index 792474af4a4abf57bfa90291284ea8ddc3408abe..8ff564515355374d8d65988acf9df8ac94bc1cdb 100644 (file)
@@ -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)
index 8dfcbcaa07c98235316fc79baf15d91cec5e2061..8ec599417e16b967c639903359011445ef2cd955 100644 (file)
@@ -590,6 +590,10 @@ public:
        std::vector<RTLIL::Wire*> selected_wires() const;
        std::vector<RTLIL::Cell*> selected_cells() const;
 
+       template<typename T> 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);
 
index ce24e09b20219399921fb9b51b66fa9f1eec2129..27571eb0d25faa37f5352e3667f6ca58073240c1 100644 (file)
@@ -21,8 +21,6 @@
 #include "kernel/sigtools.h"
 #include "kernel/modtools.h"
 
-#include <type_traits>
-
 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<std::string> args, Design *design)