Added "pmuxtree" command
authorClifford Wolf <clifford@clifford.at>
Tue, 7 Apr 2015 18:27:10 +0000 (20:27 +0200)
committerClifford Wolf <clifford@clifford.at>
Tue, 7 Apr 2015 18:27:10 +0000 (20:27 +0200)
passes/techmap/Makefile.inc
passes/techmap/pmuxtree.cc [new file with mode: 0644]
tests/various/muxcover.ys [new file with mode: 0644]

index 4f72ea6bcd03b4f7f8319a86ce2561596b4bedb8..a3e429cec3908f8b4f36c15231c42dc6d00b4550 100644 (file)
@@ -12,6 +12,7 @@ OBJS += passes/techmap/extract.o
 OBJS += passes/techmap/alumacc.o
 OBJS += passes/techmap/dff2dffe.o
 OBJS += passes/techmap/dffinit.o
+OBJS += passes/techmap/pmuxtree.o
 OBJS += passes/techmap/muxcover.o
 endif
 
diff --git a/passes/techmap/pmuxtree.cc b/passes/techmap/pmuxtree.cc
new file mode 100644 (file)
index 0000000..87762c0
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *  yosys -- Yosys Open SYnthesis Suite
+ *
+ *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
+ *  
+ *  Permission to use, copy, modify, and/or distribute this software for any
+ *  purpose with or without fee is hereby granted, provided that the above
+ *  copyright notice and this permission notice appear in all copies.
+ *  
+ *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+static SigSpec or_generator(Module *module, const SigSpec &sig)
+{
+       switch (GetSize(sig))
+       {
+       case 0:
+               return State::S0;
+       case 1:
+               return sig;
+       case 2:
+               return module->Or(NEW_ID, sig[0], sig[1]);
+       default:
+               return module->ReduceOr(NEW_ID, sig);
+       }
+}
+
+static SigSpec recursive_mux_generator(Module *module, const SigSpec &sig_data, const SigSpec &sig_sel, SigSpec &sig_or)
+{
+       if (GetSize(sig_sel) == 1) {
+               sig_or.append(sig_sel);
+               return sig_data;
+       }
+
+       int left_size = GetSize(sig_sel) / 2;
+       int right_size = GetSize(sig_sel) - left_size;
+       int stride = GetSize(sig_data) / GetSize(sig_sel);
+
+       SigSpec left_data = sig_data.extract(0, stride*left_size);
+       SigSpec right_data = sig_data.extract(stride*left_size, stride*right_size);
+
+       SigSpec left_sel = sig_sel.extract(0, left_size);
+       SigSpec right_sel = sig_sel.extract(left_size, right_size);
+
+       SigSpec left_or, left_result, right_result;
+       
+       left_result = recursive_mux_generator(module, left_data, left_sel, left_or);
+       right_result = recursive_mux_generator(module, right_data, right_sel, sig_or);
+       left_or = or_generator(module, left_or);
+       sig_or.append(left_or);
+
+       return module->Mux(NEW_ID, right_result, left_result, left_or);
+}
+
+struct PmuxtreePass : public Pass {
+       PmuxtreePass() : Pass("pmuxtree", "transform $pmux cells to trees of $mux cells") { }
+       virtual void help()
+       {
+               //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+               log("\n");
+               log("    pmuxtree [options] [selection]\n");
+               log("\n");
+               log("This pass transforms $pmux cells to a trees of $mux cells.\n");
+               log("\n");
+       }
+       virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+       {
+               log_header("Executing PMUXTREE pass.\n");
+
+               size_t argidx;
+               for (argidx = 1; argidx < args.size(); argidx++) {
+                       break;
+               }
+               extra_args(args, argidx, design);
+
+               for (auto module : design->selected_modules())
+               for (auto cell : module->selected_cells())
+               {
+                       if (cell->type != "$pmux")
+                               continue;
+
+                       SigSpec sig_data = cell->getPort("\\B");
+                       SigSpec sig_sel = cell->getPort("\\S");
+
+                       if (!cell->getPort("\\A").is_fully_undef()) {
+                               sig_data.append(cell->getPort("\\A"));
+                               SigSpec sig_sel_or = module->ReduceOr(NEW_ID, sig_sel);
+                               sig_sel.append(module->Not(NEW_ID, sig_sel_or));
+                       }
+
+                       SigSpec result, result_or;
+                       result = recursive_mux_generator(module, sig_data, sig_sel, result_or);
+                       module->connect(cell->getPort("\\Y"), result);
+                       module->remove(cell);
+               }
+       }
+} PmuxtreePass;
+
+PRIVATE_NAMESPACE_END
diff --git a/tests/various/muxcover.ys b/tests/various/muxcover.ys
new file mode 100644 (file)
index 0000000..7ac460f
--- /dev/null
@@ -0,0 +1,51 @@
+
+read_verilog -formal <<EOT
+    module gate (input [2:0] A, B, C, D, X, output reg [2:0] Y);
+        always @*
+            (* parallel_case *)
+            casez (X)
+                3'b??1: Y = A;
+                3'b?1?: Y = B;
+                3'b1??: Y = C;
+                3'b000: Y = D;
+            endcase
+    endmodule
+EOT
+
+
+## Examle usage for "pmuxtree" and "muxcover"
+
+proc
+pmuxtree
+techmap
+muxcover -mux4
+
+splitnets -ports
+clean
+# show
+
+
+## Equivalence checking
+
+read_verilog -formal <<EOT
+    module gold (input [2:0] A, B, C, D, X, output reg [2:0] Y);
+        always @*
+            casez (X)
+                3'b001: Y = A;
+                3'b010: Y = B;
+                3'b100: Y = C;
+                3'b000: Y = D;
+               default: Y = 'bx;
+            endcase
+    endmodule
+EOT
+
+proc
+splitnets -ports
+techmap -map +/simcells.v t:$_MUX4_
+
+equiv_make gold gate equiv
+hierarchy -top equiv
+equiv_simple -undef
+equiv_status -assert
+