Restore abc9 -keepff
authorEddie Hung <eddie@fpgeh.com>
Wed, 1 Jan 2020 16:34:43 +0000 (08:34 -0800)
committerEddie Hung <eddie@fpgeh.com>
Wed, 1 Jan 2020 16:34:43 +0000 (08:34 -0800)
README.md
passes/techmap/abc9.cc
techlibs/xilinx/abc9_map.v
techlibs/xilinx/synth_xilinx.cc

index c04e2b9ecb0f0a517aa9724c1686886ff6cada25..aab1c7d6b4e8311d884805bf226668f420428a08 100644 (file)
--- a/README.md
+++ b/README.md
@@ -381,9 +381,6 @@ Verilog Attributes and non-standard features
 - The module attribute ``abc9_flop`` is a boolean marking the module as a
   whitebox that describes the synchronous behaviour of a flip-flop.
 
-- The cell attribute ``abc9_keep`` is a boolean indicating that this black/
-  white box should be preserved through `abc9` mapping.
-
 - The frontend sets attributes ``always_comb``, ``always_latch`` and
   ``always_ff`` on processes derived from SystemVerilog style always blocks
   according to the type of the always. These are checked for correctness in
index d6c8260b2cac29ed8ff334018b699f03f4caeee7..a02b8d73b286385a529ea5b0b3b17c2b4a372db3 100644 (file)
@@ -249,7 +249,7 @@ struct abc9_output_filter
 };
 
 void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file,
-               bool cleanup, vector<int> lut_costs, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
+               bool cleanup, vector<int> lut_costs, bool keepff, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
                const std::vector<RTLIL::Cell*> &/*cells*/, bool show_tempdir, std::string box_file, std::string lut_file,
                std::string wire_delay, bool nomfs
 )
@@ -425,19 +425,12 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip
                                module->remove(cell);
                                continue;
                        }
+                       RTLIL::Module* box_module = design->module(cell->type);
                        auto jt = abc9_box.find(cell->type);
-                       if (jt == abc9_box.end()) {
-                               RTLIL::Module* box_module = design->module(cell->type);
+                       if (jt == abc9_box.end())
                                jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first;
-                       }
                        if (jt->second) {
-                               auto kt = cell->attributes.find("\\abc9_keep");
-                               bool abc9_keep = false;
-                               if (kt != cell->attributes.end()) {
-                                       abc9_keep = kt->second.as_bool();
-                                       cell->attributes.erase(kt);
-                               }
-                               if (!abc9_keep)
+                               if (!keepff || !box_module->get_bool_attribute("\\abc9_flop"))
                                        boxes.emplace_back(cell);
                        }
                }
@@ -802,6 +795,10 @@ struct Abc9Pass : public Pass {
                log("        generate netlist using luts. Use the specified costs for luts with 1,\n");
                log("        2, 3, .. inputs.\n");
                log("\n");
+               log("    -keepff\n");
+               log("        set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n");
+               log("        them, for example for equivalence checking.)\n");
+               log("\n");
                log("    -nocleanup\n");
                log("        when this option is used, the temporary files created by this pass\n");
                log("        are not removed. this is useful for debugging.\n");
@@ -840,7 +837,7 @@ struct Abc9Pass : public Pass {
 #endif
                std::string script_file, clk_str, box_file, lut_file;
                std::string delay_target, lutin_shared = "-S 1", wire_delay;
-               bool fast_mode = false, cleanup = true;
+               bool fast_mode = false, keepff = false, cleanup = true;
                bool show_tempdir = false;
                bool nomfs = false;
                vector<int> lut_costs;
@@ -931,6 +928,10 @@ struct Abc9Pass : public Pass {
                                fast_mode = true;
                                continue;
                        }
+                       if (arg == "-keepff") {
+                               keepff = true;
+                               continue;
+                       }
                        if (arg == "-nocleanup") {
                                cleanup = false;
                                continue;
@@ -986,36 +987,36 @@ struct Abc9Pass : public Pass {
 
                        const std::vector<RTLIL::Cell*> all_cells = module->selected_cells();
 
-                       for (auto cell : all_cells) {
-                               auto inst_module = design->module(cell->type);
-                               if (!inst_module || !inst_module->get_bool_attribute("\\abc9_flop")
-                                               || cell->get_bool_attribute("\\abc9_keep"))
-                                       continue;
+                       if (!keepff)
+                               for (auto cell : all_cells) {
+                                       auto inst_module = design->module(cell->type);
+                                       if (!inst_module || !inst_module->get_bool_attribute("\\abc9_flop"))
+                                               continue;
 
-                               Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str()));
-                               if (abc9_clock_wire == NULL)
-                                       log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
-                               SigSpec abc9_clock = assign_map(abc9_clock_wire);
-
-                               clkdomain_t key(abc9_clock);
-
-                               auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1));
-                               auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second));
-                               log_assert(r2.second);
-
-                               Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str()));
-                               if (abc9_init_wire == NULL)
-                                   log_error("'%s.$abc9_init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
-                               log_assert(GetSize(abc9_init_wire) == 1);
-                               SigSpec abc9_init = assign_map(abc9_init_wire);
-                               if (!abc9_init.is_fully_const())
-                                   log_error("'%s.$abc9_init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
-                               r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const()));
-                               log_assert(r2.second);
-                       }
+                                       Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str()));
+                                       if (abc9_clock_wire == NULL)
+                                               log_error("'%s$abc9_clock' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
+                                       SigSpec abc9_clock = assign_map(abc9_clock_wire);
+
+                                       clkdomain_t key(abc9_clock);
+
+                                       auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1));
+                                       auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second));
+                                       log_assert(r2.second);
+
+                                       Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str()));
+                                       if (abc9_init_wire == NULL)
+                                               log_error("'%s.$abc9_init' is not a wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
+                                       log_assert(GetSize(abc9_init_wire) == 1);
+                                       SigSpec abc9_init = assign_map(abc9_init_wire);
+                                       if (!abc9_init.is_fully_const())
+                                               log_error("'%s.$abc9_init' is not a constant wire present in module '%s'.\n", cell->name.c_str(), log_id(module));
+                                       r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const()));
+                                       log_assert(r2.second);
+                               }
 
                        design->selected_active_module = module->name.str();
-                       abc9_module(design, module, script_file, exe_file, cleanup, lut_costs,
+                       abc9_module(design, module, script_file, exe_file, cleanup, lut_costs, keepff,
                                        delay_target, lutin_shared, fast_mode, all_cells, show_tempdir,
                                        box_file, lut_file, wire_delay, nomfs);
                        design->selected_active_module.clear();
index 6d93e508f38e5ed5ef81ff924e422a579f5c9214..1b58c34c030f68d3fdbfb9acf90ec7bf019d3ea5 100644 (file)
@@ -21,7 +21,8 @@
 // The following techmapping rules are intended to be run (with -max_iter 1)
 //   before invoking the `abc9` pass in order to transform the design into
 //   a format that it understands.
-//
+
+`ifdef DFF_MODE
 // For example, (complex) flip-flops are expected to be described as an
 //   combinatorial box (containing all control logic such as clock enable
 //   or synchronous resets) followed by a basic D-Q flop.
@@ -83,7 +84,6 @@ module FDRE (output Q, input C, CE, D, R);
   parameter [0:0] IS_C_INVERTED = 1'b0;
   parameter [0:0] IS_D_INVERTED = 1'b0;
   parameter [0:0] IS_R_INVERTED = 1'b0;
-`ifdef DFF_MODE
   wire QQ, $Q;
   generate if (INIT == 1'b1) begin
     assign Q = ~QQ;
@@ -114,21 +114,9 @@ module FDRE (output Q, input C, CE, D, R);
   wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
   wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
   wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
-`else
-  (* abc9_keep *)
-  FDRE #(
-    .INIT(INIT),
-    .IS_C_INVERTED(IS_C_INVERTED),
-    .IS_D_INVERTED(IS_D_INVERTED),
-    .IS_R_INVERTED(IS_R_INVERTED)
-  ) _TECHMAP_REPLACE_ (
-    .D(D), .Q(Q), .C(C), .CE(CE), .R(R)
-  );
-`endif
 endmodule
 module FDRE_1 (output Q, input C, CE, D, R);
   parameter [0:0] INIT = 1'b0;
-`ifdef DFF_MODE
   wire QQ, $Q;
   generate if (INIT == 1'b1) begin
     assign Q = ~QQ;
@@ -153,14 +141,6 @@ module FDRE_1 (output Q, input C, CE, D, R);
   wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
   wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
   wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
-`else
-  (* abc9_keep *)
-  FDRE_1 #(
-    .INIT(INIT)
-  ) _TECHMAP_REPLACE_ (
-    .D(D), .Q(Q), .C(C), .CE(CE), .R(R)
-  );
-`endif
 endmodule
 
 module FDSE (output Q, input C, CE, D, S);
@@ -168,7 +148,6 @@ module FDSE (output Q, input C, CE, D, S);
   parameter [0:0] IS_C_INVERTED = 1'b0;
   parameter [0:0] IS_D_INVERTED = 1'b0;
   parameter [0:0] IS_S_INVERTED = 1'b0;
-`ifdef DFF_MODE
   wire QQ, $Q;
   generate if (INIT == 1'b1) begin
     assign Q = ~QQ;
@@ -198,21 +177,9 @@ module FDSE (output Q, input C, CE, D, S);
   wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
   wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
   wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
-`else
-  (* abc9_keep *)
-  FDSE #(
-    .INIT(INIT),
-    .IS_C_INVERTED(IS_C_INVERTED),
-    .IS_D_INVERTED(IS_D_INVERTED),
-    .IS_S_INVERTED(IS_S_INVERTED)
-  ) _TECHMAP_REPLACE_ (
-    .D(D), .Q(Q), .C(C), .CE(CE), .S(S)
-  );
-`endif
 endmodule
 module FDSE_1 (output Q, input C, CE, D, S);
   parameter [0:0] INIT = 1'b1;
-`ifdef DFF_MODE
   wire QQ, $Q;
   generate if (INIT == 1'b1) begin
     assign Q = ~QQ;
@@ -236,14 +203,6 @@ module FDSE_1 (output Q, input C, CE, D, S);
   wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
   wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
   wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
-`else
-  (* abc9_keep *)
-  FDSE_1 #(
-    .INIT(INIT)
-  ) _TECHMAP_REPLACE_ (
-    .D(D), .Q(Q), .C(C), .CE(CE), .S(S)
-  );
-`endif
 endmodule
 
 module FDCE (output Q, input C, CE, D, CLR);
@@ -251,7 +210,6 @@ module FDCE (output Q, input C, CE, D, CLR);
   parameter [0:0] IS_C_INVERTED = 1'b0;
   parameter [0:0] IS_D_INVERTED = 1'b0;
   parameter [0:0] IS_CLR_INVERTED = 1'b0;
-`ifdef DFF_MODE
   wire QQ, $Q, $abc9_currQ;
   generate if (INIT == 1'b1) begin
     assign Q = ~QQ;
@@ -295,21 +253,9 @@ module FDCE (output Q, input C, CE, D, CLR);
   wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
   wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
   wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
-`else
-  (* abc9_keep *)
-  FDCE #(
-    .INIT(INIT),
-    .IS_C_INVERTED(IS_C_INVERTED),
-    .IS_D_INVERTED(IS_D_INVERTED),
-    .IS_CLR_INVERTED(IS_CLR_INVERTED)
-  ) _TECHMAP_REPLACE_ (
-    .D(D), .Q(Q), .C(C), .CE(CE), .CLR(CLR)
-  );
-`endif
 endmodule
 module FDCE_1 (output Q, input C, CE, D, CLR);
   parameter [0:0] INIT = 1'b0;
-`ifdef DFF_MODE
   wire QQ, $Q, $abc9_currQ;
   generate if (INIT == 1'b1) begin
     assign Q = ~QQ;
@@ -345,14 +291,6 @@ module FDCE_1 (output Q, input C, CE, D, CLR);
   wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
   wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
   wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
-`else
-  (* abc9_keep *)
-  FDCE_1 #(
-    .INIT(INIT)
-  ) _TECHMAP_REPLACE_ (
-    .D(D), .Q(Q), .C(C), .CE(CE), .CLR(CLR)
-  );
-`endif
 endmodule
 
 module FDPE (output Q, input C, CE, D, PRE);
@@ -360,7 +298,6 @@ module FDPE (output Q, input C, CE, D, PRE);
   parameter [0:0] IS_C_INVERTED = 1'b0;
   parameter [0:0] IS_D_INVERTED = 1'b0;
   parameter [0:0] IS_PRE_INVERTED = 1'b0;
-`ifdef DFF_MODE
   wire QQ, $Q, $abc9_currQ;
   generate if (INIT == 1'b1) begin
     assign Q = ~QQ;
@@ -402,21 +339,9 @@ module FDPE (output Q, input C, CE, D, PRE);
   wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
   wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
   wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
-`else
-  (* abc9_keep *)
-  FDPE #(
-    .INIT(INIT),
-    .IS_C_INVERTED(IS_C_INVERTED),
-    .IS_D_INVERTED(IS_D_INVERTED),
-    .IS_PRE_INVERTED(IS_PRE_INVERTED),
-  ) _TECHMAP_REPLACE_ (
-    .D(D), .Q(Q), .C(C), .CE(CE), .PRE(PRE)
-  );
-`endif
 endmodule
 module FDPE_1 (output Q, input C, CE, D, PRE);
   parameter [0:0] INIT = 1'b1;
-`ifdef DFF_MODE
   wire QQ, $Q, $abc9_currQ;
   generate if (INIT == 1'b1) begin
     assign Q = ~QQ;
@@ -452,15 +377,8 @@ module FDPE_1 (output Q, input C, CE, D, PRE);
   wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
   wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
   wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
-`else
-  (* abc9_keep *)
-  FDPE_1 #(
-    .INIT(INIT)
-  ) _TECHMAP_REPLACE_ (
-    .D(D), .Q(Q), .C(C), .CE(CE), .PRE(PRE)
-  );
-`endif
 endmodule
+`endif
 
 // Attach a (combinatorial) black-box onto the output
 //   of thes LUTRAM primitives to capture their
index f2a9ae9823c0d0cbc80f0297b0396dac148c0f7c..10aa7be5f5dbb93fc383b54b794493ff6ad53e4f 100644 (file)
@@ -108,7 +108,7 @@ struct SynthXilinxPass : public ScriptPass
                log("        flatten design before synthesis\n");
                log("\n");
                log("    -dff\n");
-               log("        run 'abc9' with -dff option\n");
+               log("        enable sequential synthesis with 'abc9'\n");
                log("\n");
                log("    -retime\n");
                log("        run 'abc' with -dff option\n");
@@ -559,6 +559,8 @@ struct SynthXilinxPass : public ScriptPass
                                        abc9_opts += " -lut +/xilinx/abc9_xc7_nowide.lut";
                                else
                                        abc9_opts += " -lut +/xilinx/abc9_xc7.lut";
+                               if (!dff_mode)
+                                       abc9_opts += " -keepff";
                                run("abc9" + abc9_opts);
                                run("techmap -map +/xilinx/abc9_unmap.v");
                        }