mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-24 01:25:33 +00:00
Merge remote-tracking branch 'origin/master' into xaig_dff
This commit is contained in:
commit
94f15f023c
47 changed files with 2053 additions and 184 deletions
|
@ -47,6 +47,21 @@ module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .
|
|||
module \$__DFFSE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||
module \$__DFFSE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
|
||||
|
||||
`ifdef ASYNC_PRLD
|
||||
module \$_DLATCH_N_ (input E, input D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.LSR(!E), .DI(1'b0), .M(D), .Q(Q)); endmodule
|
||||
module \$_DLATCH_P_ (input E, input D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.LSR(E), .DI(1'b0), .M(D), .Q(Q)); endmodule
|
||||
|
||||
module \$_DFFSR_NNN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || !R), .DI(D), .M(R), .Q(Q)); endmodule
|
||||
module \$_DFFSR_NNP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || R), .DI(D), .M(!R), .Q(Q)); endmodule
|
||||
module \$_DFFSR_NPN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || !R), .DI(D), .M(R), .Q(Q)); endmodule
|
||||
module \$_DFFSR_NPP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || R), .DI(D), .M(!R), .Q(Q)); endmodule
|
||||
|
||||
module \$_DFFSR_PNN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || !R), .DI(D), .M(R), .Q(Q)); endmodule
|
||||
module \$_DFFSR_PNP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!S || R), .DI(D), .M(!R), .Q(Q)); endmodule
|
||||
module \$_DFFSR_PPN_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || !R), .DI(D), .M(R), .Q(Q)); endmodule
|
||||
module \$_DFFSR_PPP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || R), .DI(D), .M(!R), .Q(Q)); endmodule
|
||||
`endif
|
||||
|
||||
`include "cells_ff.vh"
|
||||
`include "cells_io.vh"
|
||||
|
||||
|
|
|
@ -79,6 +79,9 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
log(" -nowidelut\n");
|
||||
log(" do not use PFU muxes to implement LUTs larger than LUT4s\n");
|
||||
log("\n");
|
||||
log(" -asyncprld\n");
|
||||
log(" use async PRLD mode to implement DLATCH and DFFSR (EXPERIMENTAL)\n");
|
||||
log("\n");
|
||||
log(" -abc2\n");
|
||||
log(" run two passes of 'abc' for slightly improved logic density\n");
|
||||
log("\n");
|
||||
|
@ -99,7 +102,7 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
}
|
||||
|
||||
string top_opt, blif_file, edif_file, json_file;
|
||||
bool noccu2, nodffe, nobram, nolutram, nowidelut, flatten, retime, abc2, abc9, nodsp, vpr;
|
||||
bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, retime, abc2, abc9, nodsp, vpr;
|
||||
|
||||
void clear_flags() YS_OVERRIDE
|
||||
{
|
||||
|
@ -112,6 +115,7 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
nobram = false;
|
||||
nolutram = false;
|
||||
nowidelut = false;
|
||||
asyncprld = false;
|
||||
flatten = true;
|
||||
retime = false;
|
||||
abc2 = false;
|
||||
|
@ -176,6 +180,10 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
nobram = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-asyncprld") {
|
||||
asyncprld = true;
|
||||
continue;
|
||||
}
|
||||
if (args[argidx] == "-nolutram" || /*deprecated alias*/ args[argidx] == "-nodram") {
|
||||
nolutram = true;
|
||||
continue;
|
||||
|
@ -292,7 +300,7 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
run("opt_clean");
|
||||
if (!nodffe)
|
||||
run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*");
|
||||
run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
|
||||
run(stringf("techmap -D NO_LUT %s -map +/ecp5/cells_map.v", help_mode ? "[-D ASYNC_PRLD]" : (asyncprld ? "-D ASYNC_PRLD" : "")));
|
||||
run("opt_expr -undriven -mux_undef");
|
||||
run("simplemap");
|
||||
run("ecp5_ffinit");
|
||||
|
@ -306,10 +314,11 @@ struct SynthEcp5Pass : public ScriptPass
|
|||
if (abc2 || help_mode) {
|
||||
run("abc", " (only if -abc2)");
|
||||
}
|
||||
std::string techmap_args = "-map +/ecp5/latches_map.v";
|
||||
std::string techmap_args = asyncprld ? "" : "-map +/ecp5/latches_map.v";
|
||||
if (abc9)
|
||||
techmap_args += " -map +/ecp5/abc9_map.v -max_iter 1";
|
||||
run("techmap " + techmap_args);
|
||||
if (!asyncprld || abc9)
|
||||
run("techmap " + techmap_args);
|
||||
|
||||
if (abc9) {
|
||||
run("read_verilog -icells -lib +/ecp5/abc9_model.v");
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
OBJS += techlibs/xilinx/synth_xilinx.o
|
||||
OBJS += techlibs/xilinx/xilinx_dffopt.o
|
||||
|
||||
GENFILES += techlibs/xilinx/brams_init_36.vh
|
||||
GENFILES += techlibs/xilinx/brams_init_32.vh
|
||||
|
|
|
@ -28,6 +28,33 @@ module _90_dff_nn1_to_np1 (input D, C, R, output Q); \$_DFF_NP1_ _TECHMAP_REPL
|
|||
(* techmap_celltype = "$_DFF_PN1_" *)
|
||||
module _90_dff_pn1_to_pp1 (input D, C, R, output Q); \$_DFF_PP1_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
|
||||
|
||||
(* techmap_celltype = "$__DFFE_NN0" *)
|
||||
module _90_dffe_nn0_to_np0 (input D, C, R, E, output Q); \$__DFFE_NP0 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
|
||||
(* techmap_celltype = "$__DFFE_PN0" *)
|
||||
module _90_dffe_pn0_to_pp0 (input D, C, R, E, output Q); \$__DFFE_PP0 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
|
||||
(* techmap_celltype = "$__DFFE_NN1" *)
|
||||
module _90_dffe_nn1_to_np1 (input D, C, R, E, output Q); \$__DFFE_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
|
||||
(* techmap_celltype = "$__DFFE_PN1" *)
|
||||
module _90_dffe_pn1_to_pp1 (input D, C, R, E, output Q); \$__DFFE_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
|
||||
|
||||
(* techmap_celltype = "$__DFFS_NN0_" *)
|
||||
module _90_dffs_nn0_to_np0 (input D, C, R, output Q); \$__DFFS_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
|
||||
(* techmap_celltype = "$__DFFS_PN0_" *)
|
||||
module _90_dffs_pn0_to_pp0 (input D, C, R, output Q); \$__DFFS_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
|
||||
(* techmap_celltype = "$__DFFS_NN1_" *)
|
||||
module _90_dffs_nn1_to_np1 (input D, C, R, output Q); \$__DFFS_NP1_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
|
||||
(* techmap_celltype = "$__DFFS_PN1_" *)
|
||||
module _90_dffs_pn1_to_pp1 (input D, C, R, output Q); \$__DFFS_PP1_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
|
||||
|
||||
(* techmap_celltype = "$__DFFSE_NN0" *)
|
||||
module _90_dffse_nn0_to_np0 (input D, C, R, E, output Q); \$__DFFSE_NP0 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
|
||||
(* techmap_celltype = "$__DFFSE_PN0" *)
|
||||
module _90_dffse_pn0_to_pp0 (input D, C, R, E, output Q); \$__DFFSE_PP0 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
|
||||
(* techmap_celltype = "$__DFFSE_NN1" *)
|
||||
module _90_dffse_nn1_to_np1 (input D, C, R, E, output Q); \$__DFFSE_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
|
||||
(* techmap_celltype = "$__DFFSE_PN1" *)
|
||||
module _90_dffse_pn1_to_pp1 (input D, C, R, E, output Q); \$__DFFSE_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R), .E(E)); endmodule
|
||||
|
||||
module \$__SHREG_ (input C, input D, input E, output Q);
|
||||
parameter DEPTH = 0;
|
||||
parameter [DEPTH-1:0] INIT = 0;
|
||||
|
|
|
@ -320,6 +320,41 @@ module FDRE_1 (
|
|||
always @(negedge C) if (R) Q <= 1'b0; else if (CE) Q <= D;
|
||||
endmodule
|
||||
|
||||
module FDRSE (
|
||||
output reg Q,
|
||||
(* clkbuf_sink *)
|
||||
(* invertible_pin = "IS_C_INVERTED" *)
|
||||
input C,
|
||||
(* invertible_pin = "IS_CE_INVERTED" *)
|
||||
input CE,
|
||||
(* invertible_pin = "IS_D_INVERTED" *)
|
||||
input D,
|
||||
(* invertible_pin = "IS_R_INVERTED" *)
|
||||
input R,
|
||||
(* invertible_pin = "IS_S_INVERTED" *)
|
||||
input S
|
||||
);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_CE_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_D_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_R_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_S_INVERTED = 1'b0;
|
||||
initial Q <= INIT;
|
||||
wire c = C ^ IS_C_INVERTED;
|
||||
wire ce = CE ^ IS_CE_INVERTED;
|
||||
wire d = D ^ IS_D_INVERTED;
|
||||
wire r = R ^ IS_R_INVERTED;
|
||||
wire s = S ^ IS_S_INVERTED;
|
||||
always @(posedge c)
|
||||
if (r)
|
||||
Q <= 0;
|
||||
else if (s)
|
||||
Q <= 1;
|
||||
else if (ce)
|
||||
Q <= d;
|
||||
endmodule
|
||||
|
||||
(* abc9_box_id=1003, lib_whitebox, abc9_flop *)
|
||||
module FDCE (
|
||||
(* abc9_arrival=303 *)
|
||||
|
@ -1193,10 +1228,10 @@ module RAM64M (
|
|||
output DOB,
|
||||
output DOC,
|
||||
output DOD,
|
||||
input [4:0] ADDRA,
|
||||
input [4:0] ADDRB,
|
||||
input [4:0] ADDRC,
|
||||
input [4:0] ADDRD,
|
||||
input [5:0] ADDRA,
|
||||
input [5:0] ADDRB,
|
||||
input [5:0] ADDRC,
|
||||
input [5:0] ADDRD,
|
||||
input DIA,
|
||||
input DIB,
|
||||
input DIC,
|
||||
|
@ -1238,14 +1273,14 @@ module RAM64M8 (
|
|||
output DOF,
|
||||
output DOG,
|
||||
output DOH,
|
||||
input [4:0] ADDRA,
|
||||
input [4:0] ADDRB,
|
||||
input [4:0] ADDRC,
|
||||
input [4:0] ADDRD,
|
||||
input [4:0] ADDRE,
|
||||
input [4:0] ADDRF,
|
||||
input [4:0] ADDRG,
|
||||
input [4:0] ADDRH,
|
||||
input [5:0] ADDRA,
|
||||
input [5:0] ADDRB,
|
||||
input [5:0] ADDRC,
|
||||
input [5:0] ADDRD,
|
||||
input [5:0] ADDRE,
|
||||
input [5:0] ADDRF,
|
||||
input [5:0] ADDRG,
|
||||
input [5:0] ADDRH,
|
||||
input DIA,
|
||||
input DIB,
|
||||
input DIC,
|
||||
|
|
|
@ -66,7 +66,7 @@ CELLS = [
|
|||
# CLB -- registers/latches.
|
||||
# Virtex 1/2/4/5, Spartan 3.
|
||||
Cell('FDCPE', port_attrs={'C': ['clkbuf_sink']}),
|
||||
Cell('FDRSE', port_attrs={'C': ['clkbuf_sink']}),
|
||||
# Cell('FDRSE', port_attrs={'C': ['clkbuf_sink']}),
|
||||
Cell('LDCPE', port_attrs={'C': ['clkbuf_sink']}),
|
||||
# Virtex 6, Spartan 6, Series 7, Ultrascale.
|
||||
# Cell('FDCE'),
|
||||
|
|
|
@ -17,27 +17,6 @@ module FDCPE (...);
|
|||
input PRE;
|
||||
endmodule
|
||||
|
||||
module FDRSE (...);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
parameter [0:0] IS_C_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_CE_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_D_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_R_INVERTED = 1'b0;
|
||||
parameter [0:0] IS_S_INVERTED = 1'b0;
|
||||
output Q;
|
||||
(* clkbuf_sink *)
|
||||
(* invertible_pin = "IS_C_INVERTED" *)
|
||||
input C;
|
||||
(* invertible_pin = "IS_CE_INVERTED" *)
|
||||
input CE;
|
||||
(* invertible_pin = "IS_D_INVERTED" *)
|
||||
input D;
|
||||
(* invertible_pin = "IS_R_INVERTED" *)
|
||||
input R;
|
||||
(* invertible_pin = "IS_S_INVERTED" *)
|
||||
input S;
|
||||
endmodule
|
||||
|
||||
module LDCPE (...);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
parameter [0:0] IS_CLR_INVERTED = 1'b0;
|
||||
|
|
|
@ -1,4 +1,17 @@
|
|||
|
||||
bram $__XILINX_RAM16X1D
|
||||
init 1
|
||||
abits 4
|
||||
dbits 1
|
||||
groups 2
|
||||
ports 1 1
|
||||
wrmode 0 1
|
||||
enable 0 1
|
||||
transp 0 0
|
||||
clocks 0 1
|
||||
clkpol 0 2
|
||||
endbram
|
||||
|
||||
bram $__XILINX_RAM32X1D
|
||||
init 1
|
||||
abits 5
|
||||
|
@ -38,6 +51,70 @@ bram $__XILINX_RAM128X1D
|
|||
clkpol 0 2
|
||||
endbram
|
||||
|
||||
|
||||
bram $__XILINX_RAM32X6SDP
|
||||
init 1
|
||||
abits 5
|
||||
dbits 6
|
||||
groups 2
|
||||
ports 1 1
|
||||
wrmode 0 1
|
||||
enable 0 1
|
||||
transp 0 0
|
||||
clocks 0 1
|
||||
clkpol 0 2
|
||||
endbram
|
||||
|
||||
bram $__XILINX_RAM64X3SDP
|
||||
init 1
|
||||
abits 6
|
||||
dbits 3
|
||||
groups 2
|
||||
ports 1 1
|
||||
wrmode 0 1
|
||||
enable 0 1
|
||||
transp 0 0
|
||||
clocks 0 1
|
||||
clkpol 0 2
|
||||
endbram
|
||||
|
||||
bram $__XILINX_RAM32X2Q
|
||||
init 1
|
||||
abits 5
|
||||
dbits 2
|
||||
groups 2
|
||||
ports 3 1
|
||||
wrmode 0 1
|
||||
enable 0 1
|
||||
transp 0 0
|
||||
clocks 0 1
|
||||
clkpol 0 2
|
||||
endbram
|
||||
|
||||
bram $__XILINX_RAM64X1Q
|
||||
init 1
|
||||
abits 6
|
||||
dbits 1
|
||||
groups 2
|
||||
ports 3 1
|
||||
wrmode 0 1
|
||||
enable 0 1
|
||||
transp 0 0
|
||||
clocks 0 1
|
||||
clkpol 0 2
|
||||
endbram
|
||||
|
||||
|
||||
# Disabled for now, pending support for LUT4 arches
|
||||
# since on LUT6 arches this occupies same area as
|
||||
# a RAM32X1D
|
||||
#match $__XILINX_RAM16X1D
|
||||
# min bits 2
|
||||
# min wports 1
|
||||
# make_outreg
|
||||
# or_next_if_better
|
||||
#endmatch
|
||||
|
||||
match $__XILINX_RAM32X1D
|
||||
min bits 3
|
||||
min wports 1
|
||||
|
@ -56,5 +133,35 @@ match $__XILINX_RAM128X1D
|
|||
min bits 9
|
||||
min wports 1
|
||||
make_outreg
|
||||
or_next_if_better
|
||||
endmatch
|
||||
|
||||
|
||||
match $__XILINX_RAM32X6SDP
|
||||
min bits 5
|
||||
min wports 1
|
||||
make_outreg
|
||||
or_next_if_better
|
||||
endmatch
|
||||
|
||||
match $__XILINX_RAM64X3SDP
|
||||
min bits 6
|
||||
min wports 1
|
||||
make_outreg
|
||||
or_next_if_better
|
||||
endmatch
|
||||
|
||||
match $__XILINX_RAM32X2Q
|
||||
min bits 5
|
||||
min rports 3
|
||||
min wports 1
|
||||
make_outreg
|
||||
or_next_if_better
|
||||
endmatch
|
||||
|
||||
match $__XILINX_RAM64X1Q
|
||||
min bits 5
|
||||
min rports 3
|
||||
min wports 1
|
||||
make_outreg
|
||||
endmatch
|
||||
|
|
|
@ -1,4 +1,36 @@
|
|||
|
||||
module \$__XILINX_RAM16X1D (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
|
||||
parameter [15:0] INIT = 16'bx;
|
||||
parameter CLKPOL2 = 1;
|
||||
input CLK1;
|
||||
|
||||
input [3:0] A1ADDR;
|
||||
output A1DATA;
|
||||
|
||||
input [3:0] B1ADDR;
|
||||
input B1DATA;
|
||||
input B1EN;
|
||||
|
||||
RAM16X1D #(
|
||||
.INIT(INIT),
|
||||
.IS_WCLK_INVERTED(!CLKPOL2)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.DPRA0(A1ADDR[0]),
|
||||
.DPRA1(A1ADDR[1]),
|
||||
.DPRA2(A1ADDR[2]),
|
||||
.DPRA3(A1ADDR[3]),
|
||||
.DPO(A1DATA),
|
||||
|
||||
.A0(B1ADDR[0]),
|
||||
.A1(B1ADDR[1]),
|
||||
.A2(B1ADDR[2]),
|
||||
.A3(B1ADDR[3]),
|
||||
.D(B1DATA),
|
||||
.WCLK(CLK1),
|
||||
.WE(B1EN)
|
||||
);
|
||||
endmodule
|
||||
|
||||
module \$__XILINX_RAM32X1D (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
|
||||
parameter [31:0] INIT = 32'bx;
|
||||
parameter CLKPOL2 = 1;
|
||||
|
@ -95,3 +127,153 @@ module \$__XILINX_RAM128X1D (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
|
|||
);
|
||||
endmodule
|
||||
|
||||
|
||||
module \$__XILINX_RAM32X6SDP (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
|
||||
parameter [32*6-1:0] INIT = {32*6{1'bx}};
|
||||
parameter CLKPOL2 = 1;
|
||||
input CLK1;
|
||||
|
||||
input [4:0] A1ADDR;
|
||||
output [5:0] A1DATA;
|
||||
|
||||
input [4:0] B1ADDR;
|
||||
input [5:0] B1DATA;
|
||||
input B1EN;
|
||||
|
||||
wire [1:0] DOD_unused;
|
||||
|
||||
RAM32M #(
|
||||
.INIT_A({INIT[187:186], INIT[181:180], INIT[175:174], INIT[169:168], INIT[163:162], INIT[157:156], INIT[151:150], INIT[145:144], INIT[139:138], INIT[133:132], INIT[127:126], INIT[121:120], INIT[115:114], INIT[109:108], INIT[103:102], INIT[ 97: 96], INIT[ 91: 90], INIT[ 85: 84], INIT[ 79: 78], INIT[ 73: 72], INIT[ 67: 66], INIT[ 61: 60], INIT[ 55: 54], INIT[ 49: 48], INIT[ 43: 42], INIT[ 37: 36], INIT[ 31: 30], INIT[ 25: 24], INIT[ 19: 18], INIT[ 13: 12], INIT[ 7: 6], INIT[ 1: 0]}),
|
||||
.INIT_B({INIT[189:188], INIT[183:182], INIT[177:176], INIT[171:170], INIT[165:164], INIT[159:158], INIT[153:152], INIT[147:146], INIT[141:140], INIT[135:134], INIT[129:128], INIT[123:122], INIT[117:116], INIT[111:110], INIT[105:104], INIT[ 99: 98], INIT[ 93: 92], INIT[ 87: 86], INIT[ 81: 80], INIT[ 75: 74], INIT[ 69: 68], INIT[ 63: 62], INIT[ 57: 56], INIT[ 51: 50], INIT[ 45: 44], INIT[ 39: 38], INIT[ 33: 32], INIT[ 27: 26], INIT[ 21: 20], INIT[ 15: 14], INIT[ 9: 8], INIT[ 3: 2]}),
|
||||
.INIT_C({INIT[191:190], INIT[185:184], INIT[179:178], INIT[173:172], INIT[167:166], INIT[161:160], INIT[155:154], INIT[149:148], INIT[143:142], INIT[137:136], INIT[131:130], INIT[125:124], INIT[119:118], INIT[113:112], INIT[107:106], INIT[101:100], INIT[ 95: 94], INIT[ 89: 88], INIT[ 83: 82], INIT[ 77: 76], INIT[ 71: 70], INIT[ 65: 64], INIT[ 59: 58], INIT[ 53: 52], INIT[ 47: 46], INIT[ 41: 40], INIT[ 35: 34], INIT[ 29: 28], INIT[ 23: 22], INIT[ 17: 16], INIT[ 11: 10], INIT[ 5: 4]}),
|
||||
.INIT_D(64'bx),
|
||||
.IS_WCLK_INVERTED(!CLKPOL2)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.ADDRA(A1ADDR),
|
||||
.ADDRB(A1ADDR),
|
||||
.ADDRC(A1ADDR),
|
||||
.DOA(A1DATA[1:0]),
|
||||
.DOB(A1DATA[3:2]),
|
||||
.DOC(A1DATA[5:4]),
|
||||
.DOD(DOD_unused),
|
||||
|
||||
.ADDRD(B1ADDR),
|
||||
.DIA(B1DATA[1:0]),
|
||||
.DIB(B1DATA[3:2]),
|
||||
.DIC(B1DATA[5:4]),
|
||||
.DID(2'b00),
|
||||
.WCLK(CLK1),
|
||||
.WE(B1EN)
|
||||
);
|
||||
endmodule
|
||||
|
||||
module \$__XILINX_RAM64X3SDP (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
|
||||
parameter [64*3-1:0] INIT = {64*3{1'bx}};
|
||||
parameter CLKPOL2 = 1;
|
||||
input CLK1;
|
||||
|
||||
input [5:0] A1ADDR;
|
||||
output [2:0] A1DATA;
|
||||
|
||||
input [5:0] B1ADDR;
|
||||
input [2:0] B1DATA;
|
||||
input B1EN;
|
||||
|
||||
wire DOD_unused;
|
||||
|
||||
RAM64M #(
|
||||
.INIT_A({INIT[189], INIT[186], INIT[183], INIT[180], INIT[177], INIT[174], INIT[171], INIT[168], INIT[165], INIT[162], INIT[159], INIT[156], INIT[153], INIT[150], INIT[147], INIT[144], INIT[141], INIT[138], INIT[135], INIT[132], INIT[129], INIT[126], INIT[123], INIT[120], INIT[117], INIT[114], INIT[111], INIT[108], INIT[105], INIT[102], INIT[ 99], INIT[ 96], INIT[ 93], INIT[ 90], INIT[ 87], INIT[ 84], INIT[ 81], INIT[ 78], INIT[ 75], INIT[ 72], INIT[ 69], INIT[ 66], INIT[ 63], INIT[ 60], INIT[ 57], INIT[ 54], INIT[ 51], INIT[ 48], INIT[ 45], INIT[ 42], INIT[ 39], INIT[ 36], INIT[ 33], INIT[ 30], INIT[ 27], INIT[ 24], INIT[ 21], INIT[ 18], INIT[ 15], INIT[ 12], INIT[ 9], INIT[ 6], INIT[ 3], INIT[ 0]}),
|
||||
.INIT_B({INIT[190], INIT[187], INIT[184], INIT[181], INIT[178], INIT[175], INIT[172], INIT[169], INIT[166], INIT[163], INIT[160], INIT[157], INIT[154], INIT[151], INIT[148], INIT[145], INIT[142], INIT[139], INIT[136], INIT[133], INIT[130], INIT[127], INIT[124], INIT[121], INIT[118], INIT[115], INIT[112], INIT[109], INIT[106], INIT[103], INIT[100], INIT[ 97], INIT[ 94], INIT[ 91], INIT[ 88], INIT[ 85], INIT[ 82], INIT[ 79], INIT[ 76], INIT[ 73], INIT[ 70], INIT[ 67], INIT[ 64], INIT[ 61], INIT[ 58], INIT[ 55], INIT[ 52], INIT[ 49], INIT[ 46], INIT[ 43], INIT[ 40], INIT[ 37], INIT[ 34], INIT[ 31], INIT[ 28], INIT[ 25], INIT[ 22], INIT[ 19], INIT[ 16], INIT[ 13], INIT[ 10], INIT[ 7], INIT[ 4], INIT[ 1]}),
|
||||
.INIT_C({INIT[191], INIT[188], INIT[185], INIT[182], INIT[179], INIT[176], INIT[173], INIT[170], INIT[167], INIT[164], INIT[161], INIT[158], INIT[155], INIT[152], INIT[149], INIT[146], INIT[143], INIT[140], INIT[137], INIT[134], INIT[131], INIT[128], INIT[125], INIT[122], INIT[119], INIT[116], INIT[113], INIT[110], INIT[107], INIT[104], INIT[101], INIT[ 98], INIT[ 95], INIT[ 92], INIT[ 89], INIT[ 86], INIT[ 83], INIT[ 80], INIT[ 77], INIT[ 74], INIT[ 71], INIT[ 68], INIT[ 65], INIT[ 62], INIT[ 59], INIT[ 56], INIT[ 53], INIT[ 50], INIT[ 47], INIT[ 44], INIT[ 41], INIT[ 38], INIT[ 35], INIT[ 32], INIT[ 29], INIT[ 26], INIT[ 23], INIT[ 20], INIT[ 17], INIT[ 14], INIT[ 11], INIT[ 8], INIT[ 5], INIT[ 2]}),
|
||||
.INIT_D(64'bx),
|
||||
.IS_WCLK_INVERTED(!CLKPOL2)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.ADDRA(A1ADDR),
|
||||
.ADDRB(A1ADDR),
|
||||
.ADDRC(A1ADDR),
|
||||
.DOA(A1DATA[0]),
|
||||
.DOB(A1DATA[1]),
|
||||
.DOC(A1DATA[2]),
|
||||
.DOD(DOD_unused),
|
||||
|
||||
.ADDRD(B1ADDR),
|
||||
.DIA(B1DATA[0]),
|
||||
.DIB(B1DATA[1]),
|
||||
.DIC(B1DATA[2]),
|
||||
.DID(1'b0),
|
||||
.WCLK(CLK1),
|
||||
.WE(B1EN)
|
||||
);
|
||||
endmodule
|
||||
|
||||
module \$__XILINX_RAM32X2Q (CLK1, A1ADDR, A1DATA, A2ADDR, A2DATA, A3ADDR, A3DATA, B1ADDR, B1DATA, B1EN);
|
||||
parameter [63:0] INIT = 64'bx;
|
||||
parameter CLKPOL2 = 1;
|
||||
input CLK1;
|
||||
|
||||
input [4:0] A1ADDR, A2ADDR, A3ADDR;
|
||||
output [1:0] A1DATA, A2DATA, A3DATA;
|
||||
|
||||
input [4:0] B1ADDR;
|
||||
input [1:0] B1DATA;
|
||||
input B1EN;
|
||||
|
||||
RAM32M #(
|
||||
.INIT_A(INIT),
|
||||
.INIT_B(INIT),
|
||||
.INIT_C(INIT),
|
||||
.INIT_D(INIT),
|
||||
.IS_WCLK_INVERTED(!CLKPOL2)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.ADDRA(A1ADDR),
|
||||
.ADDRB(A2ADDR),
|
||||
.ADDRC(A3ADDR),
|
||||
.DOA(A1DATA),
|
||||
.DOB(A2DATA),
|
||||
.DOC(A3DATA),
|
||||
|
||||
.ADDRD(B1ADDR),
|
||||
.DIA(B1DATA),
|
||||
.DIB(B1DATA),
|
||||
.DIC(B1DATA),
|
||||
.DID(B1DATA),
|
||||
.WCLK(CLK1),
|
||||
.WE(B1EN)
|
||||
);
|
||||
endmodule
|
||||
|
||||
module \$__XILINX_RAM64X1Q (CLK1, A1ADDR, A1DATA, A2ADDR, A2DATA, A3ADDR, A3DATA, B1ADDR, B1DATA, B1EN);
|
||||
parameter [63:0] INIT = 64'bx;
|
||||
parameter CLKPOL2 = 1;
|
||||
input CLK1;
|
||||
|
||||
input [5:0] A1ADDR, A2ADDR, A3ADDR;
|
||||
output A1DATA, A2DATA, A3DATA;
|
||||
|
||||
input [5:0] B1ADDR;
|
||||
input B1DATA;
|
||||
input B1EN;
|
||||
|
||||
RAM64M #(
|
||||
.INIT_A(INIT),
|
||||
.INIT_B(INIT),
|
||||
.INIT_C(INIT),
|
||||
.INIT_D(INIT),
|
||||
.IS_WCLK_INVERTED(!CLKPOL2)
|
||||
) _TECHMAP_REPLACE_ (
|
||||
.ADDRA(A1ADDR),
|
||||
.ADDRB(A2ADDR),
|
||||
.ADDRC(A3ADDR),
|
||||
.DOA(A1DATA),
|
||||
.DOB(A2DATA),
|
||||
.DOC(A3DATA),
|
||||
|
||||
.ADDRD(B1ADDR),
|
||||
.DIA(B1DATA),
|
||||
.DIB(B1DATA),
|
||||
.DIC(B1DATA),
|
||||
.DID(B1DATA),
|
||||
.WCLK(CLK1),
|
||||
.WE(B1EN)
|
||||
);
|
||||
endmodule
|
||||
|
|
|
@ -445,6 +445,16 @@ struct SynthXilinxPass : public ScriptPass
|
|||
}
|
||||
|
||||
if (check_label("map_ffram")) {
|
||||
// Required for dffsr2dff to work.
|
||||
run("simplemap t:$dff t:$adff t:$mux");
|
||||
// Needs to be done before opt -mux_bool happens.
|
||||
run("dffsr2dff");
|
||||
if (help_mode)
|
||||
run("dff2dffs [-match-init]", "(-match-init for xc6s only)");
|
||||
else if (family == "xc6s")
|
||||
run("dff2dffs -match-init");
|
||||
else
|
||||
run("dff2dffs");
|
||||
if (widemux > 0)
|
||||
run("opt -fast -mux_bool -undriven -fine"); // Necessary to omit -mux_undef otherwise muxcover
|
||||
// performs less efficiently
|
||||
|
@ -454,14 +464,11 @@ struct SynthXilinxPass : public ScriptPass
|
|||
}
|
||||
|
||||
if (check_label("fine")) {
|
||||
run("dffsr2dff");
|
||||
run("dff2dffe");
|
||||
run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*");
|
||||
if (help_mode) {
|
||||
run("simplemap t:$mux", " ('-widemux' only)");
|
||||
run("muxcover <internal options>, ('-widemux' only)");
|
||||
}
|
||||
else if (widemux > 0) {
|
||||
run("simplemap t:$mux");
|
||||
constexpr int cost_mux2 = 100;
|
||||
std::string muxcover_args = stringf(" -nodecode -mux2=%d", cost_mux2);
|
||||
switch (widemux) {
|
||||
|
@ -563,6 +570,7 @@ struct SynthXilinxPass : public ScriptPass
|
|||
else if (!abc9)
|
||||
techmap_args += stringf(" -map %s", ff_map_file.c_str());
|
||||
run("techmap " + techmap_args, "(option without '-abc9')");
|
||||
run("xilinx_dffopt");
|
||||
}
|
||||
|
||||
if (check_label("finalize")) {
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
`ifndef _NO_FFS
|
||||
|
||||
// No reset.
|
||||
|
||||
module \$_DFF_N_ (input D, C, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
|
||||
|
@ -46,6 +48,8 @@ module \$_DFF_P_ (input D, C, output Q);
|
|||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// No reset, enable.
|
||||
|
||||
module \$_DFFE_NP_ (input D, C, E, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
|
||||
|
@ -65,15 +69,8 @@ module \$_DFFE_PP_ (input D, C, E, output Q);
|
|||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
module \$_DFF_NN0_ (input D, C, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
|
||||
$error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1");
|
||||
else
|
||||
FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
// Async reset.
|
||||
|
||||
module \$_DFF_NP0_ (input D, C, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
|
||||
|
@ -83,15 +80,6 @@ module \$_DFF_NP0_ (input D, C, R, output Q);
|
|||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$_DFF_PN0_ (input D, C, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
|
||||
$error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1");
|
||||
else
|
||||
FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$_DFF_PP0_ (input D, C, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
|
||||
|
@ -102,15 +90,6 @@ module \$_DFF_PP0_ (input D, C, R, output Q);
|
|||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
module \$_DFF_NN1_ (input D, C, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
|
||||
$error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0");
|
||||
else
|
||||
FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$_DFF_NP1_ (input D, C, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
|
||||
|
@ -120,15 +99,6 @@ module \$_DFF_NP1_ (input D, C, R, output Q);
|
|||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$_DFF_PN1_ (input D, C, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
|
||||
$error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0");
|
||||
else
|
||||
FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$_DFF_PP1_ (input D, C, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
|
||||
|
@ -139,6 +109,128 @@ module \$_DFF_PP1_ (input D, C, R, output Q);
|
|||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// Async reset, enable.
|
||||
|
||||
module \$__DFFE_NP0 (input D, C, E, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
|
||||
$error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1");
|
||||
else
|
||||
FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR( R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$__DFFE_PP0 (input D, C, E, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
|
||||
$error("Spartan 6 doesn't support FFs with asynchronous reset initialized to 1");
|
||||
else
|
||||
FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR( R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
module \$__DFFE_NP1 (input D, C, E, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
|
||||
$error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0");
|
||||
else
|
||||
FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE( R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$__DFFE_PP1 (input D, C, E, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
|
||||
$error("Spartan 6 doesn't support FFs with asynchronous set initialized to 0");
|
||||
else
|
||||
FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE( R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// Sync reset.
|
||||
|
||||
module \$__DFFS_NP0_ (input D, C, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
|
||||
$error("Spartan 6 doesn't support FFs with reset initialized to 1");
|
||||
else
|
||||
FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R( R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$__DFFS_PP0_ (input D, C, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
|
||||
$error("Spartan 6 doesn't support FFs with reset initialized to 1");
|
||||
else
|
||||
FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R( R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
module \$__DFFS_NP1_ (input D, C, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
|
||||
$error("Spartan 6 doesn't support FFs with set initialized to 0");
|
||||
else
|
||||
FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S( R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$__DFFS_PP1_ (input D, C, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
|
||||
$error("Spartan 6 doesn't support FFs with set initialized to 0");
|
||||
else
|
||||
FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S( R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// Sync reset, enable.
|
||||
|
||||
module \$__DFFSE_NP0 (input D, C, E, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
|
||||
$error("Spartan 6 doesn't support FFs with reset initialized to 1");
|
||||
else
|
||||
FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R( R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$__DFFSE_PP0 (input D, C, E, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
|
||||
$error("Spartan 6 doesn't support FFs with reset initialized to 1");
|
||||
else
|
||||
FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R( R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
module \$__DFFSE_NP1 (input D, C, E, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
|
||||
$error("Spartan 6 doesn't support FFs with set initialized to 0");
|
||||
else
|
||||
FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S( R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$__DFFSE_PP1 (input D, C, E, R, output Q);
|
||||
parameter [0:0] _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b0)
|
||||
$error("Spartan 6 doesn't support FFs with set initialized to 0");
|
||||
else
|
||||
FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S( R));
|
||||
endgenerate
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// Latches (no reset).
|
||||
|
||||
module \$_DLATCH_N_ (input E, D, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
generate if (_TECHMAP_WIREINIT_Q_ === 1'b1)
|
||||
|
@ -158,5 +250,7 @@ module \$_DLATCH_P_ (input E, D, output Q);
|
|||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// Latches with reset (TODO).
|
||||
|
||||
`endif
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
`ifndef _NO_FFS
|
||||
|
||||
// No reset.
|
||||
|
||||
module \$_DFF_N_ (input D, C, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R(1'b0));
|
||||
|
@ -48,6 +50,8 @@ module \$_DFF_P_ (input D, C, output Q);
|
|||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// No reset, enable.
|
||||
|
||||
module \$_DFFE_NP_ (input D, C, E, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0));
|
||||
|
@ -59,48 +63,104 @@ module \$_DFFE_PP_ (input D, C, E, output Q);
|
|||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
module \$_DFF_NN0_ (input D, C, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
// Async reset.
|
||||
|
||||
module \$_DFF_NP0_ (input D, C, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$_DFF_PN0_ (input D, C, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$_DFF_PP0_ (input D, C, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
module \$_DFF_NN1_ (input D, C, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$_DFF_NP1_ (input D, C, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$_DFF_PN1_ (input D, C, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$_DFF_PP1_ (input D, C, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// Async reset, enable.
|
||||
|
||||
module \$__DFFE_NP0 (input D, C, E, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDCE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$__DFFE_PP0 (input D, C, E, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDCE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .CLR( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
module \$__DFFE_NP1 (input D, C, E, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDPE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$__DFFE_PP1 (input D, C, E, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDPE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .PRE( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// Sync reset.
|
||||
|
||||
module \$__DFFS_NP0_ (input D, C, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$__DFFS_PP0_ (input D, C, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .R( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
module \$__DFFS_NP1_ (input D, C, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$__DFFS_PP1_ (input D, C, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .S( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// Sync reset, enable.
|
||||
|
||||
module \$__DFFSE_NP0 (input D, C, E, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDRE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$__DFFSE_PP0 (input D, C, E, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDRE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
module \$__DFFSE_NP1 (input D, C, E, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDSE_1 #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
module \$__DFFSE_PP1 (input D, C, E, R, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
FDSE #(.INIT(_TECHMAP_WIREINIT_Q_)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .S( R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// Latches (no reset).
|
||||
|
||||
module \$_DLATCH_N_ (input E, D, output Q);
|
||||
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
|
||||
LDCE #(.INIT(_TECHMAP_WIREINIT_Q_), .IS_G_INVERTED(1'b1)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .G(E), .GE(1'b1), .CLR(1'b0));
|
||||
|
@ -112,5 +172,7 @@ module \$_DLATCH_P_ (input E, D, output Q);
|
|||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// Latches with reset (TODO).
|
||||
|
||||
`endif
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
bram $__XILINX_RAMB36_SDP
|
||||
init 1
|
||||
abits 9
|
||||
|
@ -72,8 +71,33 @@ bram $__XILINX_RAMB18_TDP
|
|||
clkpol 2 3
|
||||
endbram
|
||||
|
||||
# The "min bits" value were taken from:
|
||||
# [[CITE]] 7 Series FPGAs Memory Resources User Guide (UG473),
|
||||
# v1.14 ed., p 29-30, July, 2019.
|
||||
# https://www.xilinx.com/support/documentation/user_guides/ug473_7Series_Memory_Resources.pdf
|
||||
|
||||
match $__XILINX_RAMB36_SDP
|
||||
min bits 4096
|
||||
attribute !ram_style
|
||||
attribute !logic_block
|
||||
min bits 1024
|
||||
min efficiency 5
|
||||
shuffle_enable B
|
||||
make_transp
|
||||
or_next_if_better
|
||||
endmatch
|
||||
|
||||
match $__XILINX_RAMB36_SDP
|
||||
attribute ram_style=block ram_block
|
||||
attribute !logic_block
|
||||
shuffle_enable B
|
||||
make_transp
|
||||
or_next_if_better
|
||||
endmatch
|
||||
|
||||
match $__XILINX_RAMB18_SDP
|
||||
attribute !ram_style
|
||||
attribute !logic_block
|
||||
min bits 1024
|
||||
min efficiency 5
|
||||
shuffle_enable B
|
||||
make_transp
|
||||
|
@ -81,7 +105,17 @@ match $__XILINX_RAMB36_SDP
|
|||
endmatch
|
||||
|
||||
match $__XILINX_RAMB18_SDP
|
||||
min bits 4096
|
||||
attribute ram_style=block ram_block
|
||||
attribute !logic_block
|
||||
shuffle_enable B
|
||||
make_transp
|
||||
or_next_if_better
|
||||
endmatch
|
||||
|
||||
match $__XILINX_RAMB36_TDP
|
||||
attribute !ram_style
|
||||
attribute !logic_block
|
||||
min bits 1024
|
||||
min efficiency 5
|
||||
shuffle_enable B
|
||||
make_transp
|
||||
|
@ -89,7 +123,17 @@ match $__XILINX_RAMB18_SDP
|
|||
endmatch
|
||||
|
||||
match $__XILINX_RAMB36_TDP
|
||||
min bits 4096
|
||||
attribute ram_style=block ram_block
|
||||
attribute !logic_block
|
||||
shuffle_enable B
|
||||
make_transp
|
||||
or_next_if_better
|
||||
endmatch
|
||||
|
||||
match $__XILINX_RAMB18_TDP
|
||||
attribute !ram_style
|
||||
attribute !logic_block
|
||||
min bits 1024
|
||||
min efficiency 5
|
||||
shuffle_enable B
|
||||
make_transp
|
||||
|
@ -97,8 +141,8 @@ match $__XILINX_RAMB36_TDP
|
|||
endmatch
|
||||
|
||||
match $__XILINX_RAMB18_TDP
|
||||
min bits 4096
|
||||
min efficiency 5
|
||||
attribute ram_style=block ram_block
|
||||
attribute !logic_block
|
||||
shuffle_enable B
|
||||
make_transp
|
||||
endmatch
|
||||
|
|
351
techlibs/xilinx/xilinx_dffopt.cc
Normal file
351
techlibs/xilinx/xilinx_dffopt.cc
Normal file
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
typedef std::pair<Const, std::vector<SigBit>> LutData;
|
||||
|
||||
// Compute a LUT implementing (select ^ select_inv) ? alt_data : data. Returns true if successful.
|
||||
bool merge_lut(LutData &result, const LutData &data, const LutData select, bool select_inv, SigBit alt_data, int max_lut_size) {
|
||||
// First, gather input signals.
|
||||
result.second = data.second;
|
||||
int idx_alt = -1;
|
||||
if (alt_data.wire) {
|
||||
// Check if we already have it.
|
||||
for (int i = 0; i < GetSize(result.second); i++)
|
||||
if (result.second[i] == alt_data)
|
||||
idx_alt = i;
|
||||
// If not, add it.
|
||||
if (idx_alt == -1) {
|
||||
idx_alt = GetSize(result.second);
|
||||
result.second.push_back(alt_data);
|
||||
}
|
||||
}
|
||||
std::vector<int> idx_sel;
|
||||
for (auto bit : select.second) {
|
||||
int idx = -1;
|
||||
for (int i = 0; i < GetSize(result.second); i++)
|
||||
if (result.second[i] == bit)
|
||||
idx = i;
|
||||
if (idx == -1) {
|
||||
idx = GetSize(result.second);
|
||||
result.second.push_back(bit);
|
||||
}
|
||||
idx_sel.push_back(idx);
|
||||
}
|
||||
|
||||
// If LUT would be too large, bail.
|
||||
if (GetSize(result.second) > max_lut_size)
|
||||
return false;
|
||||
|
||||
// Okay, we're doing it — compute the LUT mask.
|
||||
result.first = Const(0, 1 << GetSize(result.second));
|
||||
for (int i = 0; i < GetSize(result.first); i++) {
|
||||
int sel_lut_idx = 0;
|
||||
for (int j = 0; j < GetSize(select.second); j++)
|
||||
if (i & 1 << idx_sel[j])
|
||||
sel_lut_idx |= 1 << j;
|
||||
bool select_val = (select.first.bits[sel_lut_idx] == State::S1);
|
||||
bool new_bit;
|
||||
if (select_val ^ select_inv) {
|
||||
// Use alt_data.
|
||||
if (alt_data.wire)
|
||||
new_bit = (i & 1 << idx_alt) != 0;
|
||||
else
|
||||
new_bit = alt_data.data == State::S1;
|
||||
} else {
|
||||
// Use original LUT.
|
||||
int lut_idx = i & ((1 << GetSize(data.second)) - 1);
|
||||
new_bit = data.first.bits[lut_idx] == State::S1;
|
||||
}
|
||||
result.first.bits[i] = new_bit ? State::S1 : State::S0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct XilinxDffOptPass : public Pass {
|
||||
XilinxDffOptPass() : Pass("xilinx_dffopt", "Xilinx: optimize FF control signal usage") { }
|
||||
void help() YS_OVERRIDE
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" xilinx_dffopt [options] [selection]\n");
|
||||
log("\n");
|
||||
log("Converts hardware clock enable and set/reset signals on FFs to emulation\n");
|
||||
log("using LUTs, if doing so would improve area. Operates on post-techmap Xilinx\n");
|
||||
log("cells (LUT*, FD*).\n");
|
||||
log("\n");
|
||||
log(" -lut4\n");
|
||||
log(" Assume a LUT4-based device (instead of a LUT6-based device).\n");
|
||||
log("\n");
|
||||
}
|
||||
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
|
||||
{
|
||||
log_header(design, "Executing XILINX_DFFOPT pass (optimize FF control signal usage).\n");
|
||||
|
||||
size_t argidx;
|
||||
int max_lut_size = 6;
|
||||
for (argidx = 1; argidx < args.size(); argidx++)
|
||||
{
|
||||
if (args[argidx] == "-lut4") {
|
||||
max_lut_size = 4;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(args, argidx, design);
|
||||
|
||||
for (auto module : design->selected_modules())
|
||||
{
|
||||
log("Optimizing FFs in %s.\n", log_id(module));
|
||||
|
||||
SigMap sigmap(module);
|
||||
dict<SigBit, pair<LutData, Cell *>> bit_to_lut;
|
||||
dict<SigBit, int> bit_uses;
|
||||
|
||||
// Gather LUTs.
|
||||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
for (auto port : cell->connections())
|
||||
for (auto bit : port.second)
|
||||
bit_uses[sigmap(bit)]++;
|
||||
if (cell->get_bool_attribute(ID::keep))
|
||||
continue;
|
||||
if (cell->type == ID(INV)) {
|
||||
SigBit sigout = sigmap(cell->getPort(ID(O)));
|
||||
SigBit sigin = sigmap(cell->getPort(ID(I)));
|
||||
bit_to_lut[sigout] = make_pair(LutData(Const(1, 2), {sigin}), cell);
|
||||
} else if (cell->type.in(ID(LUT1), ID(LUT2), ID(LUT3), ID(LUT4), ID(LUT5), ID(LUT6))) {
|
||||
SigBit sigout = sigmap(cell->getPort(ID(O)));
|
||||
const Const &init = cell->getParam(ID(INIT));
|
||||
std::vector<SigBit> sigin;
|
||||
sigin.push_back(sigmap(cell->getPort(ID(I0))));
|
||||
if (cell->type == ID(LUT1))
|
||||
goto lut_sigin_done;
|
||||
sigin.push_back(sigmap(cell->getPort(ID(I1))));
|
||||
if (cell->type == ID(LUT2))
|
||||
goto lut_sigin_done;
|
||||
sigin.push_back(sigmap(cell->getPort(ID(I2))));
|
||||
if (cell->type == ID(LUT3))
|
||||
goto lut_sigin_done;
|
||||
sigin.push_back(sigmap(cell->getPort(ID(I3))));
|
||||
if (cell->type == ID(LUT4))
|
||||
goto lut_sigin_done;
|
||||
sigin.push_back(sigmap(cell->getPort(ID(I4))));
|
||||
if (cell->type == ID(LUT5))
|
||||
goto lut_sigin_done;
|
||||
sigin.push_back(sigmap(cell->getPort(ID(I5))));
|
||||
lut_sigin_done:
|
||||
bit_to_lut[sigout] = make_pair(LutData(init, sigin), cell);
|
||||
}
|
||||
}
|
||||
for (auto wire : module->wires())
|
||||
if (wire->port_output || wire->port_input)
|
||||
for (int i = 0; i < GetSize(wire); i++)
|
||||
bit_uses[sigmap(SigBit(wire, i))]++;
|
||||
|
||||
// Iterate through FFs.
|
||||
for (auto cell : module->selected_cells())
|
||||
{
|
||||
bool has_s = false, has_r = false;
|
||||
if (cell->type.in(ID(FDCE), ID(FDPE), ID(FDCPE), ID(FDCE_1), ID(FDPE_1), ID(FDCPE_1))) {
|
||||
// Async reset.
|
||||
} else if (cell->type.in(ID(FDRE), ID(FDRE_1))) {
|
||||
has_r = true;
|
||||
} else if (cell->type.in(ID(FDSE), ID(FDSE_1))) {
|
||||
has_s = true;
|
||||
} else if (cell->type.in(ID(FDRSE), ID(FDRSE_1))) {
|
||||
has_r = true;
|
||||
has_s = true;
|
||||
} else {
|
||||
// Not a FF.
|
||||
continue;
|
||||
}
|
||||
if (cell->get_bool_attribute(ID::keep))
|
||||
continue;
|
||||
|
||||
// Don't bother if D has more than one use.
|
||||
SigBit sig_D = sigmap(cell->getPort(ID(D)));
|
||||
if (bit_uses[sig_D] > 2)
|
||||
continue;
|
||||
|
||||
// Find the D LUT.
|
||||
auto it_D = bit_to_lut.find(sig_D);
|
||||
if (it_D == bit_to_lut.end())
|
||||
continue;
|
||||
LutData lut_d = it_D->second.first;
|
||||
Cell *cell_d = it_D->second.second;
|
||||
if (cell->hasParam(ID(IS_D_INVERTED)) && cell->getParam(ID(IS_D_INVERTED)).as_bool()) {
|
||||
// Flip all bits in the LUT.
|
||||
for (int i = 0; i < GetSize(lut_d.first); i++)
|
||||
lut_d.first.bits[i] = (lut_d.first.bits[i] == State::S1) ? State::S0 : State::S1;
|
||||
}
|
||||
|
||||
LutData lut_d_post_ce;
|
||||
LutData lut_d_post_s;
|
||||
LutData lut_d_post_r;
|
||||
bool worthy_post_ce = false;
|
||||
bool worthy_post_s = false;
|
||||
bool worthy_post_r = false;
|
||||
|
||||
// First, unmap CE.
|
||||
SigBit sig_Q = sigmap(cell->getPort(ID(Q)));
|
||||
SigBit sig_CE = sigmap(cell->getPort(ID(CE)));
|
||||
LutData lut_ce = LutData(Const(2, 2), {sig_CE});
|
||||
auto it_CE = bit_to_lut.find(sig_CE);
|
||||
if (it_CE != bit_to_lut.end())
|
||||
lut_ce = it_CE->second.first;
|
||||
if (sig_CE.wire) {
|
||||
// Merge CE LUT and D LUT into one. If it cannot be done, nothing to do about this FF.
|
||||
if (!merge_lut(lut_d_post_ce, lut_d, lut_ce, true, sig_Q, max_lut_size))
|
||||
continue;
|
||||
|
||||
// If this gets rid of a CE LUT, it's worth it. If not, it still may be worth it, if we can remove set/reset as well.
|
||||
if (it_CE != bit_to_lut.end())
|
||||
worthy_post_ce = true;
|
||||
} else if (sig_CE.data != State::S1) {
|
||||
// Strange. Should not happen in a reasonable flow, so bail.
|
||||
continue;
|
||||
} else {
|
||||
lut_d_post_ce = lut_d;
|
||||
}
|
||||
|
||||
// Second, unmap S, if any.
|
||||
lut_d_post_s = lut_d_post_ce;
|
||||
if (has_s) {
|
||||
SigBit sig_S = sigmap(cell->getPort(ID(S)));
|
||||
LutData lut_s = LutData(Const(2, 2), {sig_S});
|
||||
bool inv_s = cell->hasParam(ID(IS_S_INVERTED)) && cell->getParam(ID(IS_S_INVERTED)).as_bool();
|
||||
auto it_S = bit_to_lut.find(sig_S);
|
||||
if (it_S != bit_to_lut.end())
|
||||
lut_s = it_S->second.first;
|
||||
if (sig_S.wire) {
|
||||
// Merge S LUT and D LUT into one. If it cannot be done, try to at least merge CE.
|
||||
if (!merge_lut(lut_d_post_s, lut_d_post_ce, lut_s, inv_s, SigBit(State::S1), max_lut_size))
|
||||
goto unmap;
|
||||
// If this gets rid of an S LUT, it's worth it.
|
||||
if (it_S != bit_to_lut.end())
|
||||
worthy_post_s = true;
|
||||
} else if (sig_S.data != (inv_s ? State::S1 : State::S0)) {
|
||||
// Strange. Should not happen in a reasonable flow, so bail.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Third, unmap R, if any.
|
||||
lut_d_post_r = lut_d_post_s;
|
||||
if (has_r) {
|
||||
SigBit sig_R = sigmap(cell->getPort(ID(R)));
|
||||
LutData lut_r = LutData(Const(2, 2), {sig_R});
|
||||
bool inv_r = cell->hasParam(ID(IS_R_INVERTED)) && cell->getParam(ID(IS_R_INVERTED)).as_bool();
|
||||
auto it_R = bit_to_lut.find(sig_R);
|
||||
if (it_R != bit_to_lut.end())
|
||||
lut_r = it_R->second.first;
|
||||
if (sig_R.wire) {
|
||||
// Merge R LUT and D LUT into one. If it cannot be done, try to at least merge CE/S.
|
||||
if (!merge_lut(lut_d_post_r, lut_d_post_s, lut_r, inv_r, SigBit(State::S0), max_lut_size))
|
||||
goto unmap;
|
||||
// If this gets rid of an S LUT, it's worth it.
|
||||
if (it_R != bit_to_lut.end())
|
||||
worthy_post_r = true;
|
||||
} else if (sig_R.data != (inv_r ? State::S1 : State::S0)) {
|
||||
// Strange. Should not happen in a reasonable flow, so bail.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
unmap:
|
||||
LutData final_lut;
|
||||
if (worthy_post_r) {
|
||||
final_lut = lut_d_post_r;
|
||||
log(" Merging R LUT for %s/%s (%d -> %d)\n", log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second));
|
||||
} else if (worthy_post_s) {
|
||||
final_lut = lut_d_post_s;
|
||||
log(" Merging S LUT for %s/%s (%d -> %d)\n", log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second));
|
||||
} else if (worthy_post_ce) {
|
||||
final_lut = lut_d_post_ce;
|
||||
log(" Merging CE LUT for %s/%s (%d -> %d)\n", log_id(cell), log_id(sig_Q.wire), GetSize(lut_d.second), GetSize(final_lut.second));
|
||||
} else {
|
||||
// Nothing to do here.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Okay, we're doing it. Unmap ports.
|
||||
if (worthy_post_r) {
|
||||
cell->unsetParam(ID(IS_R_INVERTED));
|
||||
cell->setPort(ID(R), Const(0, 1));
|
||||
}
|
||||
if (has_s && (worthy_post_r || worthy_post_s)) {
|
||||
cell->unsetParam(ID(IS_S_INVERTED));
|
||||
cell->setPort(ID(S), Const(0, 1));
|
||||
}
|
||||
cell->setPort(ID(CE), Const(1, 1));
|
||||
cell->unsetParam(ID(IS_D_INVERTED));
|
||||
|
||||
// Create the new LUT.
|
||||
Cell *lut_cell = 0;
|
||||
switch (GetSize(final_lut.second)) {
|
||||
case 1:
|
||||
lut_cell = module->addCell(NEW_ID, ID(LUT1));
|
||||
break;
|
||||
case 2:
|
||||
lut_cell = module->addCell(NEW_ID, ID(LUT2));
|
||||
break;
|
||||
case 3:
|
||||
lut_cell = module->addCell(NEW_ID, ID(LUT3));
|
||||
break;
|
||||
case 4:
|
||||
lut_cell = module->addCell(NEW_ID, ID(LUT4));
|
||||
break;
|
||||
case 5:
|
||||
lut_cell = module->addCell(NEW_ID, ID(LUT5));
|
||||
break;
|
||||
case 6:
|
||||
lut_cell = module->addCell(NEW_ID, ID(LUT6));
|
||||
break;
|
||||
default:
|
||||
log_assert(!"unknown lut size");
|
||||
}
|
||||
lut_cell->attributes = cell_d->attributes;
|
||||
Wire *lut_out = module->addWire(NEW_ID);
|
||||
lut_cell->setParam(ID(INIT), final_lut.first);
|
||||
cell->setPort(ID(D), lut_out);
|
||||
lut_cell->setPort(ID(O), lut_out);
|
||||
lut_cell->setPort(ID(I0), final_lut.second[0]);
|
||||
if (GetSize(final_lut.second) >= 2)
|
||||
lut_cell->setPort(ID(I1), final_lut.second[1]);
|
||||
if (GetSize(final_lut.second) >= 3)
|
||||
lut_cell->setPort(ID(I2), final_lut.second[2]);
|
||||
if (GetSize(final_lut.second) >= 4)
|
||||
lut_cell->setPort(ID(I3), final_lut.second[3]);
|
||||
if (GetSize(final_lut.second) >= 5)
|
||||
lut_cell->setPort(ID(I4), final_lut.second[4]);
|
||||
if (GetSize(final_lut.second) >= 6)
|
||||
lut_cell->setPort(ID(I5), final_lut.second[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} XilinxDffOptPass;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue