Add -match-init option to dff2dffs.
authorMarcin Kościelnicki <koriakin@0x04.net>
Tue, 10 Sep 2019 16:31:50 +0000 (16:31 +0000)
committerMarcin Kościelnicki <koriakin@0x04.net>
Wed, 11 Sep 2019 17:38:20 +0000 (19:38 +0200)
CHANGELOG
passes/techmap/dff2dffs.cc
tests/techmap/dff2dffs.ys [new file with mode: 0644]

index e416d152c97bcf0a7c51d3464f328f2e64c7cf97..890fad9781318101207cea1fa3cf2fd8ed221552 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -39,6 +39,7 @@ Yosys 0.9 .. Yosys 0.9-dev
     - Added "xilinx_srl" for Xilinx shift register extraction
     - Removed "shregmap -tech xilinx" (superseded by "xilinx_srl")
     - Added "_TECHMAP_WIREINIT_*_" attribute and "_TECHMAP_REMOVEINIT_*_" wire for "techmap" pass
+    - Added "-match-init" option to "dff2dffs" pass
 
 Yosys 0.8 .. Yosys 0.9
 ----------------------
index 0ea03351337c9187a9143b8770be05ba6f997009..3fa1ed5cfbc0792e7c36c251cdb994711f86a175 100644 (file)
@@ -34,11 +34,16 @@ struct Dff2dffsPass : public Pass {
                log("Merge synchronous set/reset $_MUX_ cells to create $__DFFS_[NP][NP][01], to be run before\n");
                log("dff2dffe for SR over CE priority.\n");
                log("\n");
+               log("    -match-init\n");
+               log("        Disallow merging synchronous set/reset that has polarity opposite of the\n");
+               log("        output wire's init attribute (if any).\n");
+               log("\n");
        }
        void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
        {
                log_header(design, "Executing dff2dffs pass (merge synchronous set/reset into FF cells).\n");
 
+               bool match_init = false;
                size_t argidx;
                for (argidx = 1; argidx < args.size(); argidx++)
                {
@@ -46,6 +51,10 @@ struct Dff2dffsPass : public Pass {
                        //      singleton_mode = true;
                        //      continue;
                        // }
+                       if (args[argidx] == "-match-init") {
+                               match_init = true;
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
@@ -96,9 +105,6 @@ struct Dff2dffsPass : public Pass {
                                SigBit bit_b = sigmap(mux_cell->getPort(ID::B));
                                SigBit bit_s = sigmap(mux_cell->getPort(ID(S)));
 
-                               log("  Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell),
-                                               log_signal(bit_a), log_signal(bit_b), log_signal(bit_s), log_id(cell), log_id(cell->type));
-
                                SigBit sr_val, sr_sig;
                                bool invert_sr;
                                sr_sig = bit_s;
@@ -113,6 +119,23 @@ struct Dff2dffsPass : public Pass {
                                        invert_sr = false;
                                }
 
+                               if (match_init) {
+                                       SigBit bit_q = cell->getPort(ID(Q));
+                                       if (bit_q.wire) {
+                                               auto it = bit_q.wire->attributes.find(ID(init));
+                                               if (it != bit_q.wire->attributes.end()) {
+                                                       auto init_val = it->second[bit_q.offset];
+                                                       if (init_val == State::S1 && sr_val != State::S1)
+                                                               continue;
+                                                       if (init_val == State::S0 && sr_val != State::S0)
+                                                               continue;
+                                               }
+                                       }
+                               }
+
+                               log("  Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell),
+                                               log_signal(bit_a), log_signal(bit_b), log_signal(bit_s), log_id(cell), log_id(cell->type));
+
                                if (sr_val == State::S1) {
                                        if (cell->type == ID($_DFF_N_)) {
                                                if (invert_sr) cell->type = ID($__DFFS_NN1_);
diff --git a/tests/techmap/dff2dffs.ys b/tests/techmap/dff2dffs.ys
new file mode 100644 (file)
index 0000000..13f1a3c
--- /dev/null
@@ -0,0 +1,50 @@
+read_verilog << EOT
+module top(...);
+input clk;
+input d;
+input sr;
+output reg q0, q1, q2, q3, q4, q5;
+
+initial q0 = 1'b0;
+initial q1 = 1'b0;
+initial q2 = 1'b1;
+initial q3 = 1'b1;
+initial q4 = 1'bx;
+initial q5 = 1'bx;
+
+always @(posedge clk) begin
+       q0 <= sr ? 1'b0 : d;
+       q1 <= sr ? 1'b1 : d;
+       q2 <= sr ? 1'b0 : d;
+       q3 <= sr ? 1'b1 : d;
+       q4 <= sr ? 1'b0 : d;
+       q5 <= sr ? 1'b1 : d;
+end
+
+endmodule
+EOT
+
+proc
+simplemap
+design -save ref
+
+dff2dffs
+clean
+
+select -assert-count 1 w:q0 %x t:$__DFFS_PP0_ %i
+select -assert-count 1 w:q1 %x t:$__DFFS_PP1_ %i
+select -assert-count 1 w:q2 %x t:$__DFFS_PP0_ %i
+select -assert-count 1 w:q3 %x t:$__DFFS_PP1_ %i
+select -assert-count 1 w:q4 %x t:$__DFFS_PP0_ %i
+select -assert-count 1 w:q5 %x t:$__DFFS_PP1_ %i
+
+design -load ref
+dff2dffs -match-init
+clean
+
+select -assert-count 1 w:q0 %x t:$__DFFS_PP0_ %i
+select -assert-count 0 w:q1 %x t:$__DFFS_PP1_ %i
+select -assert-count 0 w:q2 %x t:$__DFFS_PP0_ %i
+select -assert-count 1 w:q3 %x t:$__DFFS_PP1_ %i
+select -assert-count 1 w:q4 %x t:$__DFFS_PP0_ %i
+select -assert-count 1 w:q5 %x t:$__DFFS_PP1_ %i