Trim init attributes when resizing FFs in "wreduce", fixes #887
authorClifford Wolf <clifford@clifford.at>
Fri, 22 Mar 2019 10:42:19 +0000 (11:42 +0100)
committerClifford Wolf <clifford@clifford.at>
Fri, 22 Mar 2019 10:42:19 +0000 (11:42 +0100)
Signed-off-by: Clifford Wolf <clifford@clifford.at>
passes/opt/wreduce.cc

index 1f7222e494b7c002a2ee7eb1be35069917554e53..52245ce3e4f9bf21e924be6128ecce36d9d64d49 100644 (file)
@@ -54,6 +54,7 @@ struct WreduceWorker
        std::set<SigBit> work_queue_bits;
        pool<SigBit> keep_bits;
        dict<SigBit, State> init_bits;
+       pool<SigBit> remove_init_bits;
 
        WreduceWorker(WreduceConfig *config, Module *module) :
                        config(config), module(module), mi(module) { }
@@ -164,6 +165,7 @@ struct WreduceWorker
                {
                        if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx)) {
                                module->connect(sig_q[i], State::S0);
+                               remove_init_bits.insert(sig_q[i]);
                                sig_d.remove(i);
                                sig_q.remove(i);
                                continue;
@@ -171,6 +173,7 @@ struct WreduceWorker
 
                        if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1]) {
                                module->connect(sig_q[i], sig_q[i-1]);
+                               remove_init_bits.insert(sig_q[i]);
                                sig_d.remove(i);
                                sig_q.remove(i);
                                continue;
@@ -178,6 +181,7 @@ struct WreduceWorker
 
                        auto info = mi.query(sig_q[i]);
                        if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) {
+                               remove_init_bits.insert(sig_q[i]);
                                sig_d.remove(i);
                                sig_q.remove(i);
                                zero_ext = false;
@@ -387,13 +391,16 @@ struct WreduceWorker
 
        void run()
        {
+               // create a copy as mi.sigmap will be updated as we process the module
+               SigMap init_attr_sigmap = mi.sigmap;
+
                for (auto w : module->wires()) {
                        if (w->get_bool_attribute("\\keep"))
                                for (auto bit : mi.sigmap(w))
                                        keep_bits.insert(bit);
                        if (w->attributes.count("\\init")) {
                                Const initval = w->attributes.at("\\init");
-                               SigSpec initsig = mi.sigmap(w);
+                               SigSpec initsig = init_attr_sigmap(w);
                                int width = std::min(GetSize(initval), GetSize(initsig));
                                for (int i = 0; i < width; i++)
                                        init_bits[initsig[i]] = initval[i];
@@ -446,6 +453,24 @@ struct WreduceWorker
                        module->connect(nw, SigSpec(w).extract(0, GetSize(nw)));
                        module->swap_names(w, nw);
                }
+
+               if (!remove_init_bits.empty()) {
+                       for (auto w : module->wires()) {
+                               if (w->attributes.count("\\init")) {
+                                       Const initval = w->attributes.at("\\init");
+                                       Const new_initval(State::Sx, GetSize(w));
+                                       SigSpec initsig = init_attr_sigmap(w);
+                                       int width = std::min(GetSize(initval), GetSize(initsig));
+                                       for (int i = 0; i < width; i++) {
+                                               log_dump(initsig[i], remove_init_bits.count(initsig[i]));
+                                               if (!remove_init_bits.count(initsig[i]))
+                                                       new_initval[i] = initval[i];
+                                       }
+                                       w->attributes.at("\\init") = new_initval;
+                                       log_dump(w->name, initval, new_initval);
+                               }
+                       }
+               }
        }
 };