Restore abc9 -keepff

This commit is contained in:
Eddie Hung 2020-01-01 08:34:43 -08:00
parent ac808c5e2a
commit c40b1aae42
4 changed files with 43 additions and 125 deletions

View File

@ -381,9 +381,6 @@ Verilog Attributes and non-standard features
- The module attribute ``abc9_flop`` is a boolean marking the module as a - The module attribute ``abc9_flop`` is a boolean marking the module as a
whitebox that describes the synchronous behaviour of a flip-flop. 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 - The frontend sets attributes ``always_comb``, ``always_latch`` and
``always_ff`` on processes derived from SystemVerilog style always blocks ``always_ff`` on processes derived from SystemVerilog style always blocks
according to the type of the always. These are checked for correctness in according to the type of the always. These are checked for correctness in

View 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, 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, const std::vector<RTLIL::Cell*> &/*cells*/, bool show_tempdir, std::string box_file, std::string lut_file,
std::string wire_delay, bool nomfs 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); module->remove(cell);
continue; continue;
} }
RTLIL::Module* box_module = design->module(cell->type);
auto jt = abc9_box.find(cell->type); auto jt = abc9_box.find(cell->type);
if (jt == abc9_box.end()) { if (jt == abc9_box.end())
RTLIL::Module* box_module = design->module(cell->type);
jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first; jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first;
}
if (jt->second) { if (jt->second) {
auto kt = cell->attributes.find("\\abc9_keep"); if (!keepff || !box_module->get_bool_attribute("\\abc9_flop"))
bool abc9_keep = false;
if (kt != cell->attributes.end()) {
abc9_keep = kt->second.as_bool();
cell->attributes.erase(kt);
}
if (!abc9_keep)
boxes.emplace_back(cell); 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(" generate netlist using luts. Use the specified costs for luts with 1,\n");
log(" 2, 3, .. inputs.\n"); log(" 2, 3, .. inputs.\n");
log("\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(" -nocleanup\n");
log(" when this option is used, the temporary files created by this pass\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"); log(" are not removed. this is useful for debugging.\n");
@ -840,7 +837,7 @@ struct Abc9Pass : public Pass {
#endif #endif
std::string script_file, clk_str, box_file, lut_file; std::string script_file, clk_str, box_file, lut_file;
std::string delay_target, lutin_shared = "-S 1", wire_delay; 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 show_tempdir = false;
bool nomfs = false; bool nomfs = false;
vector<int> lut_costs; vector<int> lut_costs;
@ -931,6 +928,10 @@ struct Abc9Pass : public Pass {
fast_mode = true; fast_mode = true;
continue; continue;
} }
if (arg == "-keepff") {
keepff = true;
continue;
}
if (arg == "-nocleanup") { if (arg == "-nocleanup") {
cleanup = false; cleanup = false;
continue; continue;
@ -986,36 +987,36 @@ struct Abc9Pass : public Pass {
const std::vector<RTLIL::Cell*> all_cells = module->selected_cells(); const std::vector<RTLIL::Cell*> all_cells = module->selected_cells();
for (auto cell : all_cells) { if (!keepff)
auto inst_module = design->module(cell->type); for (auto cell : all_cells) {
if (!inst_module || !inst_module->get_bool_attribute("\\abc9_flop") auto inst_module = design->module(cell->type);
|| cell->get_bool_attribute("\\abc9_keep")) if (!inst_module || !inst_module->get_bool_attribute("\\abc9_flop"))
continue; continue;
Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str())); Wire *abc9_clock_wire = module->wire(stringf("%s.$abc9_clock", cell->name.c_str()));
if (abc9_clock_wire == NULL) 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)); 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); SigSpec abc9_clock = assign_map(abc9_clock_wire);
clkdomain_t key(abc9_clock); clkdomain_t key(abc9_clock);
auto r = clk_to_mergeability.insert(std::make_pair(abc9_clock, clk_to_mergeability.size() + 1)); 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)); auto r2 YS_ATTRIBUTE(unused) = cell->attributes.insert(std::make_pair(ID(abc9_mergeability), r.first->second));
log_assert(r2.second); log_assert(r2.second);
Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str())); Wire *abc9_init_wire = module->wire(stringf("%s.$abc9_init", cell->name.c_str()));
if (abc9_init_wire == NULL) 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_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); log_assert(GetSize(abc9_init_wire) == 1);
SigSpec abc9_init = assign_map(abc9_init_wire); SigSpec abc9_init = assign_map(abc9_init_wire);
if (!abc9_init.is_fully_const()) 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)); 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())); r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const()));
log_assert(r2.second); log_assert(r2.second);
} }
design->selected_active_module = module->name.str(); 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, delay_target, lutin_shared, fast_mode, all_cells, show_tempdir,
box_file, lut_file, wire_delay, nomfs); box_file, lut_file, wire_delay, nomfs);
design->selected_active_module.clear(); design->selected_active_module.clear();

View File

@ -21,7 +21,8 @@
// The following techmapping rules are intended to be run (with -max_iter 1) // 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 // before invoking the `abc9` pass in order to transform the design into
// a format that it understands. // a format that it understands.
//
`ifdef DFF_MODE
// For example, (complex) flip-flops are expected to be described as an // For example, (complex) flip-flops are expected to be described as an
// combinatorial box (containing all control logic such as clock enable // combinatorial box (containing all control logic such as clock enable
// or synchronous resets) followed by a basic D-Q flop. // 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_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0;
parameter [0:0] IS_R_INVERTED = 1'b0; parameter [0:0] IS_R_INVERTED = 1'b0;
`ifdef DFF_MODE
wire QQ, $Q; wire QQ, $Q;
generate if (INIT == 1'b1) begin generate if (INIT == 1'b1) begin
assign Q = ~QQ; 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 [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_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; 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 endmodule
module FDRE_1 (output Q, input C, CE, D, R); module FDRE_1 (output Q, input C, CE, D, R);
parameter [0:0] INIT = 1'b0; parameter [0:0] INIT = 1'b0;
`ifdef DFF_MODE
wire QQ, $Q; wire QQ, $Q;
generate if (INIT == 1'b1) begin generate if (INIT == 1'b1) begin
assign Q = ~QQ; 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 [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_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; 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 endmodule
module FDSE (output Q, input C, CE, D, S); 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_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0;
parameter [0:0] IS_S_INVERTED = 1'b0; parameter [0:0] IS_S_INVERTED = 1'b0;
`ifdef DFF_MODE
wire QQ, $Q; wire QQ, $Q;
generate if (INIT == 1'b1) begin generate if (INIT == 1'b1) begin
assign Q = ~QQ; 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 [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_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; 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 endmodule
module FDSE_1 (output Q, input C, CE, D, S); module FDSE_1 (output Q, input C, CE, D, S);
parameter [0:0] INIT = 1'b1; parameter [0:0] INIT = 1'b1;
`ifdef DFF_MODE
wire QQ, $Q; wire QQ, $Q;
generate if (INIT == 1'b1) begin generate if (INIT == 1'b1) begin
assign Q = ~QQ; 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 [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_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ; 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 endmodule
module FDCE (output Q, input C, CE, D, CLR); 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_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0;
parameter [0:0] IS_CLR_INVERTED = 1'b0; parameter [0:0] IS_CLR_INVERTED = 1'b0;
`ifdef DFF_MODE
wire QQ, $Q, $abc9_currQ; wire QQ, $Q, $abc9_currQ;
generate if (INIT == 1'b1) begin generate if (INIT == 1'b1) begin
assign Q = ~QQ; 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 [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_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; 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 endmodule
module FDCE_1 (output Q, input C, CE, D, CLR); module FDCE_1 (output Q, input C, CE, D, CLR);
parameter [0:0] INIT = 1'b0; parameter [0:0] INIT = 1'b0;
`ifdef DFF_MODE
wire QQ, $Q, $abc9_currQ; wire QQ, $Q, $abc9_currQ;
generate if (INIT == 1'b1) begin generate if (INIT == 1'b1) begin
assign Q = ~QQ; 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 [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_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; 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 endmodule
module FDPE (output Q, input C, CE, D, PRE); 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_C_INVERTED = 1'b0;
parameter [0:0] IS_D_INVERTED = 1'b0; parameter [0:0] IS_D_INVERTED = 1'b0;
parameter [0:0] IS_PRE_INVERTED = 1'b0; parameter [0:0] IS_PRE_INVERTED = 1'b0;
`ifdef DFF_MODE
wire QQ, $Q, $abc9_currQ; wire QQ, $Q, $abc9_currQ;
generate if (INIT == 1'b1) begin generate if (INIT == 1'b1) begin
assign Q = ~QQ; 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 [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_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; 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 endmodule
module FDPE_1 (output Q, input C, CE, D, PRE); module FDPE_1 (output Q, input C, CE, D, PRE);
parameter [0:0] INIT = 1'b1; parameter [0:0] INIT = 1'b1;
`ifdef DFF_MODE
wire QQ, $Q, $abc9_currQ; wire QQ, $Q, $abc9_currQ;
generate if (INIT == 1'b1) begin generate if (INIT == 1'b1) begin
assign Q = ~QQ; 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 [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_init = 1'b0;
wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ; 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 endmodule
`endif
// Attach a (combinatorial) black-box onto the output // Attach a (combinatorial) black-box onto the output
// of thes LUTRAM primitives to capture their // of thes LUTRAM primitives to capture their

View File

@ -108,7 +108,7 @@ struct SynthXilinxPass : public ScriptPass
log(" flatten design before synthesis\n"); log(" flatten design before synthesis\n");
log("\n"); log("\n");
log(" -dff\n"); log(" -dff\n");
log(" run 'abc9' with -dff option\n"); log(" enable sequential synthesis with 'abc9'\n");
log("\n"); log("\n");
log(" -retime\n"); log(" -retime\n");
log(" run 'abc' with -dff option\n"); log(" run 'abc' with -dff option\n");
@ -559,6 +559,8 @@ struct SynthXilinxPass : public ScriptPass
abc9_opts += " -lut +/xilinx/abc9_xc7_nowide.lut"; abc9_opts += " -lut +/xilinx/abc9_xc7_nowide.lut";
else else
abc9_opts += " -lut +/xilinx/abc9_xc7.lut"; abc9_opts += " -lut +/xilinx/abc9_xc7.lut";
if (!dff_mode)
abc9_opts += " -keepff";
run("abc9" + abc9_opts); run("abc9" + abc9_opts);
run("techmap -map +/xilinx/abc9_unmap.v"); run("techmap -map +/xilinx/abc9_unmap.v");
} }