diff options
-rw-r--r-- | README.md | 8 | ||||
-rw-r--r-- | passes/techmap/abc9.cc | 37 | ||||
-rw-r--r-- | techlibs/xilinx/abc9_map.v | 78 | ||||
-rw-r--r-- | techlibs/xilinx/cells_sim.v | 34 |
4 files changed, 110 insertions, 47 deletions
@@ -454,10 +454,10 @@ Verilog Attributes and non-standard features expressions over parameters and constant values are allowed). The intended use for this is synthesis-time DRC. -- There is limited support for converting specify .. endspecify statements to - special ``$specify2``, ``$specify3``, and ``$specrule`` cells, for use in - blackboxes and whiteboxes. Use ``read_verilog -specify`` to enable this - functionality. (By default specify .. endspecify blocks are ignored.) +- There is limited support for converting ``specify`` .. ``endspecify`` + statements to special ``$specify2``, ``$specify3``, and ``$specrule`` cells, + for use in blackboxes and whiteboxes. Use ``read_verilog -specify`` to + enable this functionality. (By default these blocks are ignored.) Non-standard or SystemVerilog features for formal verification diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 8276c3c16..d03e5da8e 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -981,29 +981,28 @@ struct Abc9Pass : public Pass { //} if (arg == "-lut" && argidx+1 < args.size()) { string arg = args[++argidx]; - size_t pos = arg.find_first_of(':'); - int lut_mode = 0, lut_mode2 = 0; - if (pos != string::npos) { - lut_mode = atoi(arg.substr(0, pos).c_str()); - lut_mode2 = atoi(arg.substr(pos+1).c_str()); - } else { - pos = arg.find_first_of('.'); + if (arg.find_first_not_of("0123456789:") == std::string::npos) { + size_t pos = arg.find_first_of(':'); + int lut_mode = 0, lut_mode2 = 0; if (pos != string::npos) { - lut_file = arg; - rewrite_filename(lut_file); - if (!lut_file.empty() && !is_absolute_path(lut_file)) - lut_file = std::string(pwd) + "/" + lut_file; - } - else { + lut_mode = atoi(arg.substr(0, pos).c_str()); + lut_mode2 = atoi(arg.substr(pos+1).c_str()); + } else { lut_mode = atoi(arg.c_str()); lut_mode2 = lut_mode; } + lut_costs.clear(); + for (int i = 0; i < lut_mode; i++) + lut_costs.push_back(1); + for (int i = lut_mode; i < lut_mode2; i++) + lut_costs.push_back(2 << (i - lut_mode)); + } + else { + lut_file = arg; + rewrite_filename(lut_file); + if (!lut_file.empty() && !is_absolute_path(lut_file) && lut_file[0] != '+') + lut_file = std::string(pwd) + "/" + lut_file; } - lut_costs.clear(); - for (int i = 0; i < lut_mode; i++) - lut_costs.push_back(1); - for (int i = lut_mode; i < lut_mode2; i++) - lut_costs.push_back(2 << (i - lut_mode)); continue; } if (arg == "-luts" && argidx+1 < args.size()) { @@ -1072,7 +1071,7 @@ struct Abc9Pass : public Pass { box_file = "+/dummy.box"; rewrite_filename(box_file); - if (!box_file.empty() && !is_absolute_path(box_file)) + if (!box_file.empty() && !is_absolute_path(box_file) && box_file[0] != '+') box_file = std::string(pwd) + "/" + box_file; dict<int,IdString> box_lookup; diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 6fd73c1e0..7b9427b2f 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -88,6 +88,84 @@ module RAM128X1D ( \$__ABC9_LUT7 dpo (.A(\$DPO ), .S(DPRA), .Y(DPO)); endmodule +module RAM32M ( + output [1:0] DOA, + output [1:0] DOB, + output [1:0] DOC, + output [1:0] DOD, + (* techmap_autopurge *) input [4:0] ADDRA, + (* techmap_autopurge *) input [4:0] ADDRB, + (* techmap_autopurge *) input [4:0] ADDRC, + (* techmap_autopurge *) input [4:0] ADDRD, + (* techmap_autopurge *) input [1:0] DIA, + (* techmap_autopurge *) input [1:0] DIB, + (* techmap_autopurge *) input [1:0] DIC, + (* techmap_autopurge *) input [1:0] DID, + (* techmap_autopurge *) input WCLK, + (* techmap_autopurge *) input WE +); + parameter [63:0] INIT_A = 64'h0000000000000000; + parameter [63:0] INIT_B = 64'h0000000000000000; + parameter [63:0] INIT_C = 64'h0000000000000000; + parameter [63:0] INIT_D = 64'h0000000000000000; + parameter [0:0] IS_WCLK_INVERTED = 1'b0; + wire [1:0] \$DOA , \$DOB , \$DOC , \$DOD ; + RAM32M #( + .INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D), + .IS_WCLK_INVERTED(IS_WCLK_INVERTED) + ) _TECHMAP_REPLACE_ ( + .DOA(\$DOA ), .DOB(\$DOB ), .DOC(\$DOC ), .DOD(\$DOD ), + .WCLK(WCLK), .WE(WE), + .ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD), + .DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID) + ); + \$__ABC9_LUT6 doa0 (.A(\$DOA [0]), .S({1'b1, ADDRA}), .Y(DOA[0])); + \$__ABC9_LUT6 doa1 (.A(\$DOA [1]), .S({1'b1, ADDRA}), .Y(DOA[1])); + \$__ABC9_LUT6 dob0 (.A(\$DOB [0]), .S({1'b1, ADDRB}), .Y(DOB[0])); + \$__ABC9_LUT6 dob1 (.A(\$DOB [1]), .S({1'b1, ADDRB}), .Y(DOB[1])); + \$__ABC9_LUT6 doc0 (.A(\$DOC [0]), .S({1'b1, ADDRC}), .Y(DOC[0])); + \$__ABC9_LUT6 doc1 (.A(\$DOC [1]), .S({1'b1, ADDRC}), .Y(DOC[1])); + \$__ABC9_LUT6 dod0 (.A(\$DOD [0]), .S({1'b1, ADDRD}), .Y(DOD[0])); + \$__ABC9_LUT6 dod1 (.A(\$DOD [1]), .S({1'b1, ADDRD}), .Y(DOD[1])); +endmodule + +module RAM64M ( + output DOA, + output DOB, + output DOC, + output DOD, + (* techmap_autopurge *) input [5:0] ADDRA, + (* techmap_autopurge *) input [5:0] ADDRB, + (* techmap_autopurge *) input [5:0] ADDRC, + (* techmap_autopurge *) input [5:0] ADDRD, + (* techmap_autopurge *) input DIA, + (* techmap_autopurge *) input DIB, + (* techmap_autopurge *) input DIC, + (* techmap_autopurge *) input DID, + (* techmap_autopurge *) input WCLK, + (* techmap_autopurge *) input WE +); + parameter [63:0] INIT_A = 64'h0000000000000000; + parameter [63:0] INIT_B = 64'h0000000000000000; + parameter [63:0] INIT_C = 64'h0000000000000000; + parameter [63:0] INIT_D = 64'h0000000000000000; + parameter [0:0] IS_WCLK_INVERTED = 1'b0; + wire \$DOA , \$DOB , \$DOC , \$DOD ; + RAM64M #( + .INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D), + .IS_WCLK_INVERTED(IS_WCLK_INVERTED) + ) _TECHMAP_REPLACE_ ( + .DOA(\$DOA ), .DOB(\$DOB ), .DOC(\$DOC ), .DOD(\$DOD ), + .WCLK(WCLK), .WE(WE), + .ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD), + .DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID) + ); + \$__ABC9_LUT6 doa (.A(\$DOA ), .S(ADDRA), .Y(DOA)); + \$__ABC9_LUT6 dob (.A(\$DOB ), .S(ADDRB), .Y(DOB)); + \$__ABC9_LUT6 doc (.A(\$DOC ), .S(ADDRC), .Y(DOC)); + \$__ABC9_LUT6 dod (.A(\$DOD ), .S(ADDRD), .Y(DOD)); +endmodule + module SRL16E ( output Q, (* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v index 47ba794bf..804c2d70f 100644 --- a/techlibs/xilinx/cells_sim.v +++ b/techlibs/xilinx/cells_sim.v @@ -1244,18 +1244,11 @@ endmodule // Multi port. module RAM32M ( - output [1:0] DOA, - output [1:0] DOB, - output [1:0] DOC, - output [1:0] DOD, - input [4:0] ADDRA, - input [4:0] ADDRB, - input [4:0] ADDRC, - input [4:0] ADDRD, - input [1:0] DIA, - input [1:0] DIB, - input [1:0] DIC, - input [1:0] DID, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + (* abc9_arrival=1153 *) + output [1:0] DOA, DOB, DOC, DOD, + input [4:0] ADDRA, ADDRB, ADDRC, ADDRD, + input [1:0] DIA, DIB, DIC, DID, (* clkbuf_sink *) (* invertible_pin = "IS_WCLK_INVERTED" *) input WCLK, @@ -1354,18 +1347,11 @@ module RAM32M16 ( endmodule module RAM64M ( - output DOA, - output DOB, - output DOC, - output DOD, - input [5:0] ADDRA, - input [5:0] ADDRB, - input [5:0] ADDRC, - input [5:0] ADDRD, - input DIA, - input DIB, - input DIC, - input DID, + // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957 + (* abc9_arrival=1153 *) + output DOA, DOB, DOC, DOD, + input [5:0] ADDRA, ADDRB, ADDRC, ADDRD, + input DIA, DIB, DIC, DID, (* clkbuf_sink *) (* invertible_pin = "IS_WCLK_INVERTED" *) input WCLK, |