3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-07-28 23:17:57 +00:00

synth_nexus to synth_lattice

This commit is contained in:
Miodrag Milanovic 2023-08-31 13:17:21 +02:00
parent 567e803f14
commit 247613e649
21 changed files with 160 additions and 476 deletions

View file

@ -4,28 +4,40 @@ OBJS += techlibs/lattice/lattice_gsr.o
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_ff.vh))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_io.vh))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_map.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_map_trellis.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_map_nexus.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/common_sim.vh))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/parse_init.vh))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/ccu2d_sim.vh))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/ccu2c_sim.vh))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_ecp5.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_xo2.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_xo3.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_xo3d.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_nexus.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_ecp5.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_xo2.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_xo3.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_xo3d.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_map.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams.txt))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_nexus.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_map_trellis.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_trellis.txt))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_map_nexus.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_nexus.txt))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lrams_map_nexus.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/lrams_nexus.txt))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_map_16kd.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_16kd.txt))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_map_8kc.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_8kc.txt))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_map_nexus.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_nexus.txt))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/arith_map_ccu2c.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/arith_map_ccu2d.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/arith_map_nexus.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/latches_map.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/dsp_map_18x18.v))
$(eval $(call add_share_file,share/lattice,techlibs/lattice/dsp_map_nexus.v))
$(eval $(call add_share_file,share/ecp5,techlibs/lattice/cells_ff.vh))
@ -34,3 +46,7 @@ $(eval $(call add_share_file,share/ecp5,techlibs/lattice/common_sim.vh))
$(eval $(call add_share_file,share/ecp5,techlibs/lattice/ccu2c_sim.vh))
$(eval $(call add_share_file_and_rename,share/ecp5,techlibs/lattice/cells_sim_ecp5.v,cells_sim.v))
$(eval $(call add_share_file_and_rename,share/ecp5,techlibs/lattice/cells_bb_ecp5.v,cells_bb.v))
$(eval $(call add_share_file,share/nexus,techlibs/lattice/parse_init.vh))
$(eval $(call add_share_file_and_rename,share/nexus,techlibs/lattice/cells_sim_nexus.v,cells_sim.v))
$(eval $(call add_share_file_and_rename,share/nexus,techlibs/lattice/cells_bb_nexus.v,cells_xtra.v))

View file

@ -0,0 +1,99 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2018 gatecat <gatecat@ds0.me>
*
* 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.
*
*/
(* techmap_celltype = "$alu" *)
module _80_nexus_alu (A, B, CI, BI, X, Y, CO);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
(* force_downto *)
input [A_WIDTH-1:0] A;
(* force_downto *)
input [B_WIDTH-1:0] B;
(* force_downto *)
output [Y_WIDTH-1:0] X, Y;
input CI, BI;
(* force_downto *)
output [Y_WIDTH-1:0] CO;
wire _TECHMAP_FAIL_ = Y_WIDTH <= 4;
(* force_downto *)
wire [Y_WIDTH-1:0] A_buf, B_buf;
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
function integer round_up2;
input integer N;
begin
round_up2 = ((N + 1) / 2) * 2;
end
endfunction
localparam Y_WIDTH2 = round_up2(Y_WIDTH);
(* force_downto *)
wire [Y_WIDTH2-1:0] AA = A_buf;
(* force_downto *)
wire [Y_WIDTH2-1:0] BB = BI ? ~B_buf : B_buf;
(* force_downto *)
wire [Y_WIDTH2-1:0] BX = B_buf;
(* force_downto *)
wire [Y_WIDTH2+1:0] FCO, Y1;
genvar i;
// Carry feed-in
CCU2 #(
.INIT0("0xFFFF"),
.INIT1("0x00AA"),
.INJECT("NO")
) ccu2c_i (
.A0(1'b1), .B0(1'b1), .C0(1'b1), .D0(1'b1),
.A1(CI), .B1(1'b1), .C1(1'b1), .D1(1'b1),
.COUT(FCO[0])
);
generate for (i = 0; i < Y_WIDTH2; i = i + 2) begin:slice
CCU2 #(
.INIT0("0x96AA"),
.INIT1("0x96AA"),
.INJECT("NO")
) ccu2c_i (
.CIN(FCO[i]),
.A0(AA[i]), .B0(BX[i]), .C0(BI), .D0(1'b1),
.A1(AA[i+1]), .B1(BX[i+1]), .C1(BI), .D1(1'b1),
.S0(Y[i]), .S1(Y1[i]),
.COUT(FCO[i+2])
);
assign CO[i] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i]));
if (i+1 < Y_WIDTH) begin
assign CO[i + 1] = (AA[i + 1] && BB[i + 1]) || ((Y[i + 1] ^ AA[i + 1] ^ BB[i + 1]) && (AA[i + 1] || BB[i + 1]));
assign Y[i+1] = Y1[i];
end
end endgenerate
assign X = AA ^ BB;
endmodule

View file

@ -0,0 +1,420 @@
module $__NX_DP16K_ (...);
parameter INIT = 0;
parameter PORT_A_OPTION_RESETMODE = "SYNC";
parameter PORT_A_WIDTH = 18;
parameter PORT_A_WR_BE_WIDTH = 2;
input PORT_A_CLK;
input PORT_A_CLK_EN;
input PORT_A_WR_EN;
input PORT_A_RD_SRST;
input PORT_A_RD_ARST;
input [13:0] PORT_A_ADDR;
input [PORT_A_WR_BE_WIDTH-1:0] PORT_A_WR_BE;
input [PORT_A_WIDTH-1:0] PORT_A_WR_DATA;
output [PORT_A_WIDTH-1:0] PORT_A_RD_DATA;
parameter PORT_B_OPTION_RESETMODE = "SYNC";
parameter PORT_B_WIDTH = 18;
parameter PORT_B_WR_BE_WIDTH = 2;
input PORT_B_CLK;
input PORT_B_CLK_EN;
input PORT_B_WR_EN;
input PORT_B_RD_SRST;
input PORT_B_RD_ARST;
input [13:0] PORT_B_ADDR;
input [PORT_B_WR_BE_WIDTH-1:0] PORT_B_WR_BE;
input [PORT_B_WIDTH-1:0] PORT_B_WR_DATA;
output [PORT_B_WIDTH-1:0] PORT_B_RD_DATA;
function [319:0] init_slice;
input integer idx;
integer i;
init_slice = 0;
for (i = 0; i < 32; i = i + 1) begin
init_slice[i*10+:9] = INIT[(idx * 32 + i) * 9+:9];
end
endfunction
wire [17:0] DOA;
wire [17:0] DOB;
wire [17:0] DIA = PORT_A_WR_DATA;
wire [17:0] DIB = PORT_B_WR_DATA;
wire [13:0] ADA;
wire [13:0] ADB;
generate
case(PORT_A_WIDTH)
1: assign ADA = PORT_A_ADDR;
2: assign ADA = {PORT_A_ADDR[13:1], 1'b1};
4: assign ADA = {PORT_A_ADDR[13:2], 2'b11};
9: assign ADA = {PORT_A_ADDR[13:3], 3'b111};
18: assign ADA = {PORT_A_ADDR[13:4], 2'b11, PORT_A_WR_BE};
endcase
case(PORT_B_WIDTH)
1: assign ADB = PORT_B_ADDR;
2: assign ADB = {PORT_B_ADDR[13:1], 1'b1};
4: assign ADB = {PORT_B_ADDR[13:2], 2'b11};
9: assign ADB = {PORT_B_ADDR[13:3], 3'b111};
18: assign ADB = {PORT_B_ADDR[13:4], 2'b11, PORT_B_WR_BE};
endcase
endgenerate
assign PORT_A_RD_DATA = DOA;
assign PORT_B_RD_DATA = DOB;
DP16K #(
.INITVAL_00($sformatf("0x%080x", init_slice('h00))),
.INITVAL_01($sformatf("0x%080x", init_slice('h01))),
.INITVAL_02($sformatf("0x%080x", init_slice('h02))),
.INITVAL_03($sformatf("0x%080x", init_slice('h03))),
.INITVAL_04($sformatf("0x%080x", init_slice('h04))),
.INITVAL_05($sformatf("0x%080x", init_slice('h05))),
.INITVAL_06($sformatf("0x%080x", init_slice('h06))),
.INITVAL_07($sformatf("0x%080x", init_slice('h07))),
.INITVAL_08($sformatf("0x%080x", init_slice('h08))),
.INITVAL_09($sformatf("0x%080x", init_slice('h09))),
.INITVAL_0A($sformatf("0x%080x", init_slice('h0a))),
.INITVAL_0B($sformatf("0x%080x", init_slice('h0b))),
.INITVAL_0C($sformatf("0x%080x", init_slice('h0c))),
.INITVAL_0D($sformatf("0x%080x", init_slice('h0d))),
.INITVAL_0E($sformatf("0x%080x", init_slice('h0e))),
.INITVAL_0F($sformatf("0x%080x", init_slice('h0f))),
.INITVAL_10($sformatf("0x%080x", init_slice('h10))),
.INITVAL_11($sformatf("0x%080x", init_slice('h11))),
.INITVAL_12($sformatf("0x%080x", init_slice('h12))),
.INITVAL_13($sformatf("0x%080x", init_slice('h13))),
.INITVAL_14($sformatf("0x%080x", init_slice('h14))),
.INITVAL_15($sformatf("0x%080x", init_slice('h15))),
.INITVAL_16($sformatf("0x%080x", init_slice('h16))),
.INITVAL_17($sformatf("0x%080x", init_slice('h17))),
.INITVAL_18($sformatf("0x%080x", init_slice('h18))),
.INITVAL_19($sformatf("0x%080x", init_slice('h19))),
.INITVAL_1A($sformatf("0x%080x", init_slice('h1a))),
.INITVAL_1B($sformatf("0x%080x", init_slice('h1b))),
.INITVAL_1C($sformatf("0x%080x", init_slice('h1c))),
.INITVAL_1D($sformatf("0x%080x", init_slice('h1d))),
.INITVAL_1E($sformatf("0x%080x", init_slice('h1e))),
.INITVAL_1F($sformatf("0x%080x", init_slice('h1f))),
.INITVAL_20($sformatf("0x%080x", init_slice('h20))),
.INITVAL_21($sformatf("0x%080x", init_slice('h21))),
.INITVAL_22($sformatf("0x%080x", init_slice('h22))),
.INITVAL_23($sformatf("0x%080x", init_slice('h23))),
.INITVAL_24($sformatf("0x%080x", init_slice('h24))),
.INITVAL_25($sformatf("0x%080x", init_slice('h25))),
.INITVAL_26($sformatf("0x%080x", init_slice('h26))),
.INITVAL_27($sformatf("0x%080x", init_slice('h27))),
.INITVAL_28($sformatf("0x%080x", init_slice('h28))),
.INITVAL_29($sformatf("0x%080x", init_slice('h29))),
.INITVAL_2A($sformatf("0x%080x", init_slice('h2a))),
.INITVAL_2B($sformatf("0x%080x", init_slice('h2b))),
.INITVAL_2C($sformatf("0x%080x", init_slice('h2c))),
.INITVAL_2D($sformatf("0x%080x", init_slice('h2d))),
.INITVAL_2E($sformatf("0x%080x", init_slice('h2e))),
.INITVAL_2F($sformatf("0x%080x", init_slice('h2f))),
.INITVAL_30($sformatf("0x%080x", init_slice('h30))),
.INITVAL_31($sformatf("0x%080x", init_slice('h31))),
.INITVAL_32($sformatf("0x%080x", init_slice('h32))),
.INITVAL_33($sformatf("0x%080x", init_slice('h33))),
.INITVAL_34($sformatf("0x%080x", init_slice('h34))),
.INITVAL_35($sformatf("0x%080x", init_slice('h35))),
.INITVAL_36($sformatf("0x%080x", init_slice('h36))),
.INITVAL_37($sformatf("0x%080x", init_slice('h37))),
.INITVAL_38($sformatf("0x%080x", init_slice('h38))),
.INITVAL_39($sformatf("0x%080x", init_slice('h39))),
.INITVAL_3A($sformatf("0x%080x", init_slice('h3a))),
.INITVAL_3B($sformatf("0x%080x", init_slice('h3b))),
.INITVAL_3C($sformatf("0x%080x", init_slice('h3c))),
.INITVAL_3D($sformatf("0x%080x", init_slice('h3d))),
.INITVAL_3E($sformatf("0x%080x", init_slice('h3e))),
.INITVAL_3F($sformatf("0x%080x", init_slice('h3f))),
.DATA_WIDTH_A($sformatf("X%d", PORT_A_WIDTH)),
.DATA_WIDTH_B($sformatf("X%d", PORT_B_WIDTH)),
.OUTREG_A("BYPASSED"),
.OUTREG_B("BYPASSED"),
.RESETMODE_A(PORT_A_OPTION_RESETMODE),
.RESETMODE_B(PORT_B_OPTION_RESETMODE),
.ASYNC_RST_RELEASE_A(PORT_A_OPTION_RESETMODE),
.ASYNC_RST_RELEASE_B(PORT_B_OPTION_RESETMODE),
.CSDECODE_A("111"),
.CSDECODE_B("111"),
.GSR("DISABLED"),
) _TECHMAP_REPLACE_ (
.CLKA(PORT_A_CLK),
.WEA(PORT_A_WIDTH == 18 ? PORT_A_WR_EN : (PORT_A_WR_EN | PORT_A_WR_BE[0])),
.CEA(PORT_A_CLK_EN),
.RSTA(PORT_A_OPTION_RESETMODE == "SYNC" ? PORT_A_RD_SRST : PORT_A_RD_ARST),
.CSA(3'b111),
.DIA(DIA),
.DOA(DOA),
.ADA(ADA),
.CLKB(PORT_B_CLK),
.WEB(PORT_B_WIDTH == 18 ? PORT_B_WR_EN : (PORT_B_WR_EN | PORT_B_WR_BE[0])),
.CEB(PORT_B_CLK_EN),
.RSTB(PORT_B_OPTION_RESETMODE == "SYNC" ? PORT_B_RD_SRST : PORT_B_RD_ARST),
.CSB(3'b111),
.ADB(ADB),
.DIB(DIB),
.DOB(DOB),
);
endmodule
module $__NX_PDP16K_ (...);
parameter INIT = 0;
parameter OPTION_SAME_CLOCK = 1;
parameter PORT_R_WIDTH = 36;
parameter PORT_R_OPTION_RESETMODE = "SYNC";
input CLK_C;
input PORT_R_CLK;
input PORT_R_CLK_EN;
input PORT_R_RD_SRST;
input PORT_R_RD_ARST;
input [13:0] PORT_R_ADDR;
output [PORT_R_WIDTH-1:0] PORT_R_RD_DATA;
parameter PORT_W_WIDTH = 36;
parameter PORT_W_WR_EN_WIDTH = 4;
input PORT_W_CLK;
input PORT_W_CLK_EN;
input [13:0] PORT_W_ADDR;
input [PORT_W_WR_EN_WIDTH-1:0] PORT_W_WR_EN;
input [PORT_W_WIDTH-1:0] PORT_W_WR_DATA;
function [319:0] init_slice;
input integer idx;
integer i;
init_slice = 0;
for (i = 0; i < 32; i = i + 1) begin
init_slice[i*10+:9] = INIT[(idx * 32 + i) * 9+:9];
end
endfunction
wire [35:0] DI = PORT_W_WR_DATA;
wire [35:0] DO;
assign PORT_R_RD_DATA = DO;
wire [13:0] ADW;
wire [13:0] ADR;
generate
case (PORT_W_WIDTH)
1: assign ADW = PORT_W_ADDR;
2: assign ADW = {PORT_W_ADDR[13:1], 1'b1};
4: assign ADW = {PORT_W_ADDR[13:2], 2'b11};
9: assign ADW = {PORT_W_ADDR[13:3], 3'b111};
18: assign ADW = {PORT_W_ADDR[13:4], 2'b11, PORT_W_WR_EN};
36: assign ADW = {PORT_W_ADDR[13:5], 1'b1, PORT_W_WR_EN};
endcase
case (PORT_R_WIDTH)
1: assign ADR = PORT_R_ADDR;
2: assign ADR = {PORT_R_ADDR[13:1], 1'b1};
4: assign ADR = {PORT_R_ADDR[13:2], 2'b11};
9: assign ADR = {PORT_R_ADDR[13:3], 3'b111};
18: assign ADR = {PORT_R_ADDR[13:4], 4'b1111};
36: assign ADR = {PORT_R_ADDR[13:5], 5'b11111};
endcase
if (OPTION_SAME_CLOCK) begin
PDPSC16K #(
.INITVAL_00($sformatf("0x%080x", init_slice('h00))),
.INITVAL_01($sformatf("0x%080x", init_slice('h01))),
.INITVAL_02($sformatf("0x%080x", init_slice('h02))),
.INITVAL_03($sformatf("0x%080x", init_slice('h03))),
.INITVAL_04($sformatf("0x%080x", init_slice('h04))),
.INITVAL_05($sformatf("0x%080x", init_slice('h05))),
.INITVAL_06($sformatf("0x%080x", init_slice('h06))),
.INITVAL_07($sformatf("0x%080x", init_slice('h07))),
.INITVAL_08($sformatf("0x%080x", init_slice('h08))),
.INITVAL_09($sformatf("0x%080x", init_slice('h09))),
.INITVAL_0A($sformatf("0x%080x", init_slice('h0a))),
.INITVAL_0B($sformatf("0x%080x", init_slice('h0b))),
.INITVAL_0C($sformatf("0x%080x", init_slice('h0c))),
.INITVAL_0D($sformatf("0x%080x", init_slice('h0d))),
.INITVAL_0E($sformatf("0x%080x", init_slice('h0e))),
.INITVAL_0F($sformatf("0x%080x", init_slice('h0f))),
.INITVAL_10($sformatf("0x%080x", init_slice('h10))),
.INITVAL_11($sformatf("0x%080x", init_slice('h11))),
.INITVAL_12($sformatf("0x%080x", init_slice('h12))),
.INITVAL_13($sformatf("0x%080x", init_slice('h13))),
.INITVAL_14($sformatf("0x%080x", init_slice('h14))),
.INITVAL_15($sformatf("0x%080x", init_slice('h15))),
.INITVAL_16($sformatf("0x%080x", init_slice('h16))),
.INITVAL_17($sformatf("0x%080x", init_slice('h17))),
.INITVAL_18($sformatf("0x%080x", init_slice('h18))),
.INITVAL_19($sformatf("0x%080x", init_slice('h19))),
.INITVAL_1A($sformatf("0x%080x", init_slice('h1a))),
.INITVAL_1B($sformatf("0x%080x", init_slice('h1b))),
.INITVAL_1C($sformatf("0x%080x", init_slice('h1c))),
.INITVAL_1D($sformatf("0x%080x", init_slice('h1d))),
.INITVAL_1E($sformatf("0x%080x", init_slice('h1e))),
.INITVAL_1F($sformatf("0x%080x", init_slice('h1f))),
.INITVAL_20($sformatf("0x%080x", init_slice('h20))),
.INITVAL_21($sformatf("0x%080x", init_slice('h21))),
.INITVAL_22($sformatf("0x%080x", init_slice('h22))),
.INITVAL_23($sformatf("0x%080x", init_slice('h23))),
.INITVAL_24($sformatf("0x%080x", init_slice('h24))),
.INITVAL_25($sformatf("0x%080x", init_slice('h25))),
.INITVAL_26($sformatf("0x%080x", init_slice('h26))),
.INITVAL_27($sformatf("0x%080x", init_slice('h27))),
.INITVAL_28($sformatf("0x%080x", init_slice('h28))),
.INITVAL_29($sformatf("0x%080x", init_slice('h29))),
.INITVAL_2A($sformatf("0x%080x", init_slice('h2a))),
.INITVAL_2B($sformatf("0x%080x", init_slice('h2b))),
.INITVAL_2C($sformatf("0x%080x", init_slice('h2c))),
.INITVAL_2D($sformatf("0x%080x", init_slice('h2d))),
.INITVAL_2E($sformatf("0x%080x", init_slice('h2e))),
.INITVAL_2F($sformatf("0x%080x", init_slice('h2f))),
.INITVAL_30($sformatf("0x%080x", init_slice('h30))),
.INITVAL_31($sformatf("0x%080x", init_slice('h31))),
.INITVAL_32($sformatf("0x%080x", init_slice('h32))),
.INITVAL_33($sformatf("0x%080x", init_slice('h33))),
.INITVAL_34($sformatf("0x%080x", init_slice('h34))),
.INITVAL_35($sformatf("0x%080x", init_slice('h35))),
.INITVAL_36($sformatf("0x%080x", init_slice('h36))),
.INITVAL_37($sformatf("0x%080x", init_slice('h37))),
.INITVAL_38($sformatf("0x%080x", init_slice('h38))),
.INITVAL_39($sformatf("0x%080x", init_slice('h39))),
.INITVAL_3A($sformatf("0x%080x", init_slice('h3a))),
.INITVAL_3B($sformatf("0x%080x", init_slice('h3b))),
.INITVAL_3C($sformatf("0x%080x", init_slice('h3c))),
.INITVAL_3D($sformatf("0x%080x", init_slice('h3d))),
.INITVAL_3E($sformatf("0x%080x", init_slice('h3e))),
.INITVAL_3F($sformatf("0x%080x", init_slice('h3f))),
.DATA_WIDTH_W($sformatf("X%d", PORT_W_WIDTH)),
.DATA_WIDTH_R($sformatf("X%d", PORT_R_WIDTH)),
.OUTREG("BYPASSED"),
.RESETMODE(PORT_R_OPTION_RESETMODE),
.ASYNC_RST_RELEASE(PORT_R_OPTION_RESETMODE),
.CSDECODE_W("111"),
.CSDECODE_R("111"),
.ECC("DISABLED"),
.GSR("DISABLED"),
) _TECHMAP_REPLACE_ (
.CLK(CLK_C),
.CEW(PORT_W_CLK_EN & (|PORT_W_WR_EN)),
.CSW(3'b111),
.ADW(ADW),
.DI(DI),
.CER(PORT_R_CLK_EN),
.RST(PORT_R_OPTION_RESETMODE == "SYNC" ? PORT_R_RD_SRST : PORT_R_RD_ARST),
.CSR(3'b111),
.ADR(ADR),
.DO(DO),
);
end else begin
PDP16K #(
.INITVAL_00($sformatf("0x%080x", init_slice('h00))),
.INITVAL_01($sformatf("0x%080x", init_slice('h01))),
.INITVAL_02($sformatf("0x%080x", init_slice('h02))),
.INITVAL_03($sformatf("0x%080x", init_slice('h03))),
.INITVAL_04($sformatf("0x%080x", init_slice('h04))),
.INITVAL_05($sformatf("0x%080x", init_slice('h05))),
.INITVAL_06($sformatf("0x%080x", init_slice('h06))),
.INITVAL_07($sformatf("0x%080x", init_slice('h07))),
.INITVAL_08($sformatf("0x%080x", init_slice('h08))),
.INITVAL_09($sformatf("0x%080x", init_slice('h09))),
.INITVAL_0A($sformatf("0x%080x", init_slice('h0a))),
.INITVAL_0B($sformatf("0x%080x", init_slice('h0b))),
.INITVAL_0C($sformatf("0x%080x", init_slice('h0c))),
.INITVAL_0D($sformatf("0x%080x", init_slice('h0d))),
.INITVAL_0E($sformatf("0x%080x", init_slice('h0e))),
.INITVAL_0F($sformatf("0x%080x", init_slice('h0f))),
.INITVAL_10($sformatf("0x%080x", init_slice('h10))),
.INITVAL_11($sformatf("0x%080x", init_slice('h11))),
.INITVAL_12($sformatf("0x%080x", init_slice('h12))),
.INITVAL_13($sformatf("0x%080x", init_slice('h13))),
.INITVAL_14($sformatf("0x%080x", init_slice('h14))),
.INITVAL_15($sformatf("0x%080x", init_slice('h15))),
.INITVAL_16($sformatf("0x%080x", init_slice('h16))),
.INITVAL_17($sformatf("0x%080x", init_slice('h17))),
.INITVAL_18($sformatf("0x%080x", init_slice('h18))),
.INITVAL_19($sformatf("0x%080x", init_slice('h19))),
.INITVAL_1A($sformatf("0x%080x", init_slice('h1a))),
.INITVAL_1B($sformatf("0x%080x", init_slice('h1b))),
.INITVAL_1C($sformatf("0x%080x", init_slice('h1c))),
.INITVAL_1D($sformatf("0x%080x", init_slice('h1d))),
.INITVAL_1E($sformatf("0x%080x", init_slice('h1e))),
.INITVAL_1F($sformatf("0x%080x", init_slice('h1f))),
.INITVAL_20($sformatf("0x%080x", init_slice('h20))),
.INITVAL_21($sformatf("0x%080x", init_slice('h21))),
.INITVAL_22($sformatf("0x%080x", init_slice('h22))),
.INITVAL_23($sformatf("0x%080x", init_slice('h23))),
.INITVAL_24($sformatf("0x%080x", init_slice('h24))),
.INITVAL_25($sformatf("0x%080x", init_slice('h25))),
.INITVAL_26($sformatf("0x%080x", init_slice('h26))),
.INITVAL_27($sformatf("0x%080x", init_slice('h27))),
.INITVAL_28($sformatf("0x%080x", init_slice('h28))),
.INITVAL_29($sformatf("0x%080x", init_slice('h29))),
.INITVAL_2A($sformatf("0x%080x", init_slice('h2a))),
.INITVAL_2B($sformatf("0x%080x", init_slice('h2b))),
.INITVAL_2C($sformatf("0x%080x", init_slice('h2c))),
.INITVAL_2D($sformatf("0x%080x", init_slice('h2d))),
.INITVAL_2E($sformatf("0x%080x", init_slice('h2e))),
.INITVAL_2F($sformatf("0x%080x", init_slice('h2f))),
.INITVAL_30($sformatf("0x%080x", init_slice('h30))),
.INITVAL_31($sformatf("0x%080x", init_slice('h31))),
.INITVAL_32($sformatf("0x%080x", init_slice('h32))),
.INITVAL_33($sformatf("0x%080x", init_slice('h33))),
.INITVAL_34($sformatf("0x%080x", init_slice('h34))),
.INITVAL_35($sformatf("0x%080x", init_slice('h35))),
.INITVAL_36($sformatf("0x%080x", init_slice('h36))),
.INITVAL_37($sformatf("0x%080x", init_slice('h37))),
.INITVAL_38($sformatf("0x%080x", init_slice('h38))),
.INITVAL_39($sformatf("0x%080x", init_slice('h39))),
.INITVAL_3A($sformatf("0x%080x", init_slice('h3a))),
.INITVAL_3B($sformatf("0x%080x", init_slice('h3b))),
.INITVAL_3C($sformatf("0x%080x", init_slice('h3c))),
.INITVAL_3D($sformatf("0x%080x", init_slice('h3d))),
.INITVAL_3E($sformatf("0x%080x", init_slice('h3e))),
.INITVAL_3F($sformatf("0x%080x", init_slice('h3f))),
.DATA_WIDTH_W($sformatf("X%d", PORT_W_WIDTH)),
.DATA_WIDTH_R($sformatf("X%d", PORT_R_WIDTH)),
.OUTREG("BYPASSED"),
.RESETMODE(PORT_R_OPTION_RESETMODE),
.ASYNC_RST_RELEASE(PORT_R_OPTION_RESETMODE),
.CSDECODE_W("111"),
.CSDECODE_R("111"),
.ECC("DISABLED"),
.GSR("DISABLED"),
) _TECHMAP_REPLACE_ (
.CLKW(PORT_W_CLK),
.CEW(PORT_W_CLK_EN & (|PORT_W_WR_EN)),
.CSW(3'b111),
.ADW(ADW),
.DI(DI),
.CLKR(PORT_R_CLK),
.CER(PORT_R_CLK_EN),
.RST(PORT_R_OPTION_RESETMODE == "SYNC" ? PORT_R_RD_SRST : PORT_R_RD_ARST),
.CSR(3'b111),
.ADR(ADR),
.DO(DO),
);
end
endgenerate
endmodule

View file

@ -0,0 +1,47 @@
ram block $__NX_DP16K_ {
abits 14;
widths 1 2 4 9 18 per_port;
byte 9;
cost 129;
init no_undef;
port srsw "A" "B" {
clock posedge;
clken;
wrbe_separate;
rdwr no_change;
portoption "RESETMODE" "SYNC" {
rdsrst zero gated_clken;
}
portoption "RESETMODE" "ASYNC" {
rdarst zero;
}
rdinit zero;
}
}
ram block $__NX_PDP16K_ {
abits 14;
widths 1 2 4 9 18 36 per_port;
byte 9;
option "SAME_CLOCK" 1 cost 128;
option "SAME_CLOCK" 0 cost 129;
init no_undef;
port sr "R" {
option "SAME_CLOCK" 1 clock posedge "C";
option "SAME_CLOCK" 0 clock posedge;
clken;
portoption "RESETMODE" "SYNC" {
rdsrst zero gated_clken;
}
portoption "RESETMODE" "ASYNC" {
rdarst zero;
}
rdinit zero;
}
port sw "W" {
option "SAME_CLOCK" 1 clock posedge "C";
option "SAME_CLOCK" 0 clock posedge;
clken;
option "SAME_CLOCK" 1 wrtrans all old;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,98 @@
// Flipflop intermediate map level
module \$__FF_NOLSR (input D, C, E, output Q);
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
generate
if (_TECHMAP_WIREINIT_Q_ === 1'b1)
FD1P3JX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .PD(1'b0), .Q(Q));
else
FD1P3IX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .CD(1'b0), .Q(Q));
endgenerate
endmodule
module \$__FF_SYNCLSR (input D, C, E, R, output Q);
parameter SR_VAL = 1'b0;
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
wire Ci, Ei, Ri, Rg, Dd;
generate
if (SR_VAL)
FD1P3JX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .PD(R), .Q(Q));
else
FD1P3IX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .CD(R), .Q(Q));
endgenerate
endmodule
module \$__FF_ASYNCLSR (input D, C, E, R, output Q);
parameter SR_VAL = 1'b0;
parameter _TECHMAP_WIREINIT_Q_ = 1'bx;
wire _TECHMAP_REMOVEINIT_Q_ = (_TECHMAP_WIREINIT_Q_ === 1'bx || _TECHMAP_WIREINIT_Q_ === SR_VAL);
wire Ci, Ei, Ri, Rg, Dd;
generate
if (SR_VAL)
FD1P3BX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .PD(R), .Q(Q));
else
FD1P3DX #(.GSR("DISABLED")) _TECHMAP_REPLACE_ (.D(D), .CK(C), .SP(E), .CD(R), .Q(Q));
endgenerate
endmodule
module \$_DFF_P_ (input D, C, output Q); \$__FF_NOLSR _TECHMAP_REPLACE_ (.D(D), .C(C), .E(1'b1), .Q(Q)); endmodule
module \$_DFFE_PP_ (input D, C, E, output Q); \$__FF_NOLSR _TECHMAP_REPLACE_ (.D(D), .C(C), .E(E), .Q(Q)); endmodule
module \$_DFF_PP0_ (input D, C, R, output Q); \$__FF_ASYNCLSR #(0) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(1'b1), .Q(Q)); endmodule
module \$_DFF_PP1_ (input D, C, R, output Q); \$__FF_ASYNCLSR #(1) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(1'b1), .Q(Q)); endmodule
module \$_SDFF_PP0_ (input D, C, R, output Q); \$__FF_SYNCLSR #(0) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(1'b1), .Q(Q)); endmodule
module \$_SDFF_PP1_ (input D, C, R, output Q); \$__FF_SYNCLSR #(1) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(1'b1), .Q(Q)); endmodule
module \$_DFFE_PP0P_ (input D, C, E, R, output Q); \$__FF_ASYNCLSR #(0) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(E), .Q(Q)); endmodule
module \$_DFFE_PP1P_ (input D, C, E, R, output Q); \$__FF_ASYNCLSR #(1) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(E), .Q(Q)); endmodule
module \$_SDFFE_PP0P_ (input D, C, E, R, output Q); \$__FF_SYNCLSR #(0) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(E), .Q(Q)); endmodule
module \$_SDFFE_PP1P_ (input D, C, E, R, output Q); \$__FF_SYNCLSR #(1) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(E), .Q(Q)); endmodule
`ifndef NO_LUT
module \$lut (A, Y);
parameter WIDTH = 0;
parameter LUT = 0;
input [WIDTH-1:0] A;
output Y;
generate
if (WIDTH == 1) begin
if (LUT == 2'b01)
INV _TECHMAP_REPLACE_ (.A(A[0]), .Z(Y));
else
LUT4 #(.INIT($sformatf("0x%04x", {{8{LUT[1]}}, {8{LUT[0]}}}))) _TECHMAP_REPLACE_ (.Z(Y),
.D(A[0]));
end else
if (WIDTH == 2) begin
localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[2]}}, {4{LUT[1]}}, {4{LUT[0]}}};
LUT4 #(.INIT($sformatf("0x%04x", INIT))) _TECHMAP_REPLACE_ (.Z(Y),
.C(A[0]), .D(A[1]));
end else
if (WIDTH == 3) begin
localparam [15:0] INIT = {{2{LUT[7]}}, {2{LUT[6]}}, {2{LUT[5]}}, {2{LUT[4]}}, {2{LUT[3]}}, {2{LUT[2]}}, {2{LUT[1]}}, {2{LUT[0]}}};
LUT4 #(.INIT($sformatf("0x%04x", INIT))) _TECHMAP_REPLACE_ (.Z(Y),
.B(A[0]), .C(A[1]), .D(A[2]));
end else
if (WIDTH == 4) begin
LUT4 #(.INIT($sformatf("0x%04x", LUT))) _TECHMAP_REPLACE_ (.Z(Y),
.A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
end else
if (WIDTH == 5) begin
WIDEFN9 #(
.INIT0($sformatf("0x%04x", LUT[15:0 ])),
.INIT1($sformatf("0x%04x", LUT[31:16])),
) _TECHMAP_REPLACE_ (
.A0(A[0]), .B0(A[1]), .C0(A[2]), .D0(A[3]),
.A1(A[0]), .B1(A[1]), .C1(A[2]), .D1(A[3]),
.SEL(A[4]), .Z(Y)
);
end
endgenerate
endmodule
`endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,286 @@
#!/usr/bin/env python3
# Based on Xilinx cells_xtra.py; modified for Radiant's structure
from argparse import ArgumentParser
from io import StringIO
from enum import Enum, auto
import os.path
import sys
import re
class Cell:
def __init__(self, name, keep=False, port_attrs={}):
self.name = name
self.keep = keep
self.port_attrs = port_attrs
self.found = False
class State(Enum):
OUTSIDE = auto()
IN_MODULE = auto()
IN_OTHER_MODULE = auto()
IN_FUNCTION = auto()
IN_TASK = auto()
devices = [
("lifcl", [
Cell("ACC54"),
Cell("ADC"),
Cell("ALUREG"),
Cell("BB_ADC", keep=True),
Cell("BB_CDR", keep=True),
Cell("BB_I3C_A", keep=True),
Cell("BFD1P3KX"),
Cell("BFD1P3LX"),
Cell("BNKREF18", keep=True),
Cell("CONFIG_LMMI", keep=True),
Cell("DCC"),
Cell("DCS"),
Cell("DDRDLL"),
Cell("DELAYA"),
Cell("DELAYB"),
Cell("DIFFIO18", keep=True),
Cell("DLLDEL"),
Cell("DP16K_MODE"),
Cell("DP16K"),
Cell("DPHY", keep=True),
Cell("DPSC512K"),
Cell("DQSBUF"),
Cell("EBR_CORE"),
Cell("EBR"),
Cell("ECLKDIV"),
Cell("ECLKSYNC"),
Cell("FBMUX"),
Cell("FIFO16K_MODE"),
Cell("FIFO16K"),
Cell("GSR"),
Cell("HSE"),
Cell("I2CFIFO"),
Cell("IDDR71"),
Cell("IDDRX1"),
Cell("IDDRX2DQ"),
Cell("IDDRX2"),
Cell("IDDRX4DQ"),
Cell("IDDRX4"),
Cell("IDDRX5"),
Cell("IFD1P3BX"),
Cell("IFD1P3DX"),
Cell("IFD1P3IX"),
Cell("IFD1P3JX"),
Cell("JTAG", keep=True),
Cell("LRAM"),
Cell("M18X36"),
Cell("MIPI"),
Cell("MULT18"),
# Cell("MULT18X18"),
# Cell("MULT18X36"),
Cell("MULT36"),
# Cell("MULT36X36"),
Cell("MULT9"),
# Cell("MULT9X9"),
# Cell("MULTADDSUB18X18"),
Cell("MULTADDSUB18X18WIDE"),
# Cell("MULTADDSUB18X36"),
# Cell("MULTADDSUB36X36"),
Cell("MULTADDSUB9X9WIDE"),
Cell("MULTIBOOT", keep=True),
# Cell("MULTPREADD18X18"),
# Cell("MULTPREADD9X9"),
Cell("ODDR71"),
Cell("ODDRX1"),
Cell("ODDRX2DQS"),
Cell("ODDRX2DQ"),
Cell("ODDRX2"),
Cell("ODDRX4DQS"),
Cell("ODDRX4DQ"),
Cell("ODDRX4"),
Cell("ODDRX5"),
Cell("OFD1P3BX"),
Cell("OFD1P3DX"),
Cell("OFD1P3IX"),
Cell("OFD1P3JX"),
Cell("OSC"),
Cell("OSCA"),
Cell("OSHX2"),
Cell("OSHX4"),
Cell("PCIE"),
Cell("PCLKDIV"),
Cell("PCLKDIVSP"),
Cell("PDP16K_MODE"),
Cell("PDP16K"),
Cell("PDPSC16K_MODE"),
Cell("PDPSC16K"),
Cell("PDPSC512K"),
Cell("PLL"),
Cell("PREADD9"),
Cell("PUR", keep=True),
Cell("REFMUX"),
Cell("REG18"),
Cell("SEDC", keep=True),
Cell("SEIO18"),
Cell("SEIO33"),
Cell("SGMIICDR"),
Cell("SP16K_MODE"),
Cell("SP16K"),
Cell("SP512K"),
Cell("TSALLA"),
Cell("TSHX2DQS"),
Cell("TSHX2DQ"),
Cell("TSHX4DQS"),
Cell("TSHX4DQ"),
Cell("WDT", keep=True),
Cell("ACC54_CORE"),
Cell("ADC_CORE"),
Cell("ALUREG_CORE"),
Cell("BNKREF18_CORE"),
Cell("BNKREF33_CORE"),
Cell("DIFFIO18_CORE"),
Cell("CONFIG_CLKRST_CORE", keep=True),
Cell("CONFIG_HSE_CORE", keep=True),
Cell("CONFIG_IP_CORE", keep=True),
Cell("CONFIG_JTAG_CORE", keep=True),
Cell("CONFIG_LMMI_CORE", keep=True),
Cell("CONFIG_MULTIBOOT_CORE", keep=True),
Cell("CONFIG_SEDC_CORE", keep=True),
Cell("CONFIG_WDT_CORE", keep=True),
Cell("DDRDLL_CORE"),
Cell("DLLDEL_CORE"),
Cell("DPHY_CORE"),
Cell("DQSBUF_CORE"),
Cell("ECLKDIV_CORE"),
Cell("ECLKSYNC_CORE"),
Cell("FBMUX_CORE"),
Cell("GSR_CORE"),
Cell("I2CFIFO_CORE"),
Cell("LRAM_CORE"),
Cell("MULT18_CORE"),
Cell("MULT18X36_CORE"),
Cell("MULT36_CORE"),
Cell("MULT9_CORE"),
Cell("OSC_CORE"),
Cell("PCIE_CORE"),
Cell("PLL_CORE"),
Cell("PREADD9_CORE"),
Cell("REFMUX_CORE"),
Cell("REG18_CORE"),
Cell("SEIO18_CORE"),
Cell("SEIO33_CORE"),
Cell("SGMIICDR_CORE"),
])
]
def xtract_cells_decl(device, cells, dirs, outf):
fname = os.path.join(dir, device + '.v')
with open(fname) as f:
state = State.OUTSIDE
# Probably the most horrible Verilog "parser" ever written.
cell = None
for l in f:
l, _, comment = l.partition('//')
l = l.strip()
if l.startswith("module "):
cell_name = l[7:l.find('(')].strip()
cell = None
module_ports = []
iopad_pin = set()
if state != State.OUTSIDE:
print('Nested modules in {}.'.format(fname))
sys.exit(1)
for c in cells:
if c.name != cell_name:
continue
cell = c
state = State.IN_MODULE
if cell.keep:
outf.write('(* keep *)\n')
outf.write('module {} (...);\n'.format(cell.name))
cell.found = True
m = re.search(r'synthesis .*black_box_pad_pin="([^"]*)"', comment)
if m:
iopad_pin = set(m.group(1).split(","))
if cell is None:
state = State.IN_OTHER_MODULE
elif l.startswith('task '):
if state == State.IN_MODULE:
state = State.IN_TASK
elif l.startswith('function '):
if state == State.IN_MODULE:
state = State.IN_FUNCTION
elif l == 'endtask':
if state == State.IN_TASK:
state = State.IN_MODULE
elif l == 'endfunction':
if state == State.IN_FUNCTION:
state = State.IN_MODULE
elif l == 'endmodule':
if state == State.IN_MODULE:
for kind, rng, port in module_ports:
for attr in cell.port_attrs.get(port, []):
outf.write(' (* {} *)\n'.format(attr))
if port in iopad_pin:
outf.write(' (* iopad_external_pin *)\n')
if rng is None:
outf.write(' {} {};\n'.format(kind, port))
else:
outf.write(' {} {} {};\n'.format(kind, rng, port))
outf.write(l + '\n')
outf.write('\n')
elif state != State.IN_OTHER_MODULE:
print('endmodule in weird place in {}.'.format(cell.name, fname))
sys.exit(1)
state = State.OUTSIDE
elif l.startswith(('input ', 'output ', 'inout ')) and state == State.IN_MODULE:
if l.endswith((';', ',')):
l = l[:-1]
if ';' in l:
print('Weird port line in {} [{}].'.format(fname, l))
sys.exit(1)
kind, _, ports = l.partition(' ')
for port in ports.split(','):
port = port.strip()
if port.startswith('['):
rng, port = port.split()
else:
rng = None
module_ports.append((kind, rng, port))
elif l.startswith('parameter ') and state == State.IN_MODULE:
if l.endswith((';', ',')):
l = l[:-1]
while ' ' in l:
l = l.replace(' ', ' ')
if ';' in l:
print('Weird parameter line in {} [{}].'.format(fname, l))
sys.exit(1)
outf.write(' {};\n'.format(l))
if state != State.OUTSIDE:
print('endmodule not found in {}.'.format(fname))
sys.exit(1)
for cell in cells:
if not cell.found:
print('cell {} not found in {}.'.format(cell.name, fname))
if __name__ == '__main__':
parser = ArgumentParser(description='Extract Lattice blackbox cell definitions from Radiant.')
parser.add_argument('radiant_dir', nargs='?', default='/opt/lscc/radiant/2.0/')
args = parser.parse_args()
dirs = [
os.path.join(args.radiant_dir, 'cae_library/synthesis/verilog/'),
]
for dir in dirs:
if not os.path.isdir(dir):
print('{} is not a directory'.format(dir))
out = StringIO()
for device, cells in devices:
xtract_cells_decl(device, cells, dirs, out)
with open('cells_bb_nexus.v', 'w') as f:
f.write('// Created by cells_xtra_nexus.py from Lattice models\n')
f.write('\n')
f.write(out.getvalue())

View file

@ -0,0 +1,79 @@
module \$__NX_MUL36X36 (input [35:0] A, input [35:0] B, output [71:0] Y);
parameter A_WIDTH = 36;
parameter B_WIDTH = 36;
parameter Y_WIDTH = 72;
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
MULT36X36 #(
.REGINPUTA("BYPASS"),
.REGINPUTB("BYPASS"),
.REGOUTPUT("BYPASS")
) _TECHMAP_REPLACE_ (
.A(A), .B(B),
.SIGNEDA(A_SIGNED ? 1'b1 : 1'b0),
.SIGNEDB(B_SIGNED ? 1'b1 : 1'b0),
.Z(Y)
);
endmodule
module \$__NX_MUL36X18 (input [35:0] A, input [17:0] B, output [53:0] Y);
parameter A_WIDTH = 36;
parameter B_WIDTH = 18;
parameter Y_WIDTH = 54;
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
MULT18X36 #(
.REGINPUTA("BYPASS"),
.REGINPUTB("BYPASS"),
.REGOUTPUT("BYPASS")
) _TECHMAP_REPLACE_ (
.A(B), .B(A),
.SIGNEDA(B_SIGNED ? 1'b1 : 1'b0),
.SIGNEDB(A_SIGNED ? 1'b1 : 1'b0),
.Z(Y)
);
endmodule
module \$__NX_MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y);
parameter A_WIDTH = 18;
parameter B_WIDTH = 18;
parameter Y_WIDTH = 36;
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
MULT18X18 #(
.REGINPUTA("BYPASS"),
.REGINPUTB("BYPASS"),
.REGOUTPUT("BYPASS")
) _TECHMAP_REPLACE_ (
.A(A), .B(B),
.SIGNEDA(A_SIGNED ? 1'b1 : 1'b0),
.SIGNEDB(B_SIGNED ? 1'b1 : 1'b0),
.Z(Y)
);
endmodule
module \$__NX_MUL9X9 (input [8:0] A, input [8:0] B, output [17:0] Y);
parameter A_WIDTH = 9;
parameter B_WIDTH = 9;
parameter Y_WIDTH = 18;
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
MULT9X9 #(
.REGINPUTA("BYPASS"),
.REGINPUTB("BYPASS"),
.REGOUTPUT("BYPASS")
) _TECHMAP_REPLACE_ (
.A(A), .B(B),
.SIGNEDA(A_SIGNED ? 1'b1 : 1'b0),
.SIGNEDB(B_SIGNED ? 1'b1 : 1'b0),
.Z(Y)
);
endmodule

View file

@ -0,0 +1,194 @@
module $__NX_DPSC512K_ (...);
parameter INIT = 0;
parameter OPTION_RESETMODE = "SYNC";
input CLK_C;
input PORT_A_CLK;
input PORT_A_CLK_EN;
input PORT_A_WR_EN;
input PORT_A_RD_SRST;
input PORT_A_RD_ARST;
input [13:0] PORT_A_ADDR;
input [3:0] PORT_A_WR_BE;
input [31:0] PORT_A_WR_DATA;
output [31:0] PORT_A_RD_DATA;
input PORT_B_CLK;
input PORT_B_CLK_EN;
input PORT_B_WR_EN;
input PORT_B_RD_SRST;
input PORT_B_RD_ARST;
input [13:0] PORT_B_ADDR;
input [3:0] PORT_B_WR_BE;
input [31:0] PORT_B_WR_DATA;
output [31:0] PORT_B_RD_DATA;
function [5119:0] init_slice;
input integer idx;
integer i, j;
init_slice = 0;
for (i = 0; i < 128; i = i + 1) begin
init_slice[i*40+:32] = INIT[(idx * 128 + i) * 32+:32];
end
endfunction
DPSC512K #(
.INITVAL_00($sformatf("0x%01280x", init_slice('h00))),
.INITVAL_01($sformatf("0x%01280x", init_slice('h01))),
.INITVAL_02($sformatf("0x%01280x", init_slice('h02))),
.INITVAL_03($sformatf("0x%01280x", init_slice('h03))),
.INITVAL_04($sformatf("0x%01280x", init_slice('h04))),
.INITVAL_05($sformatf("0x%01280x", init_slice('h05))),
.INITVAL_06($sformatf("0x%01280x", init_slice('h06))),
.INITVAL_07($sformatf("0x%01280x", init_slice('h07))),
.INITVAL_08($sformatf("0x%01280x", init_slice('h08))),
.INITVAL_09($sformatf("0x%01280x", init_slice('h09))),
.INITVAL_0A($sformatf("0x%01280x", init_slice('h0a))),
.INITVAL_0B($sformatf("0x%01280x", init_slice('h0b))),
.INITVAL_0C($sformatf("0x%01280x", init_slice('h0c))),
.INITVAL_0D($sformatf("0x%01280x", init_slice('h0d))),
.INITVAL_0E($sformatf("0x%01280x", init_slice('h0e))),
.INITVAL_0F($sformatf("0x%01280x", init_slice('h0f))),
.INITVAL_10($sformatf("0x%01280x", init_slice('h10))),
.INITVAL_11($sformatf("0x%01280x", init_slice('h11))),
.INITVAL_12($sformatf("0x%01280x", init_slice('h12))),
.INITVAL_13($sformatf("0x%01280x", init_slice('h13))),
.INITVAL_14($sformatf("0x%01280x", init_slice('h14))),
.INITVAL_15($sformatf("0x%01280x", init_slice('h15))),
.INITVAL_16($sformatf("0x%01280x", init_slice('h16))),
.INITVAL_17($sformatf("0x%01280x", init_slice('h17))),
.INITVAL_18($sformatf("0x%01280x", init_slice('h18))),
.INITVAL_19($sformatf("0x%01280x", init_slice('h19))),
.INITVAL_1A($sformatf("0x%01280x", init_slice('h1a))),
.INITVAL_1B($sformatf("0x%01280x", init_slice('h1b))),
.INITVAL_1C($sformatf("0x%01280x", init_slice('h1c))),
.INITVAL_1D($sformatf("0x%01280x", init_slice('h1d))),
.INITVAL_1E($sformatf("0x%01280x", init_slice('h1e))),
.INITVAL_1F($sformatf("0x%01280x", init_slice('h1f))),
.INITVAL_20($sformatf("0x%01280x", init_slice('h20))),
.INITVAL_21($sformatf("0x%01280x", init_slice('h21))),
.INITVAL_22($sformatf("0x%01280x", init_slice('h22))),
.INITVAL_23($sformatf("0x%01280x", init_slice('h23))),
.INITVAL_24($sformatf("0x%01280x", init_slice('h24))),
.INITVAL_25($sformatf("0x%01280x", init_slice('h25))),
.INITVAL_26($sformatf("0x%01280x", init_slice('h26))),
.INITVAL_27($sformatf("0x%01280x", init_slice('h27))),
.INITVAL_28($sformatf("0x%01280x", init_slice('h28))),
.INITVAL_29($sformatf("0x%01280x", init_slice('h29))),
.INITVAL_2A($sformatf("0x%01280x", init_slice('h2a))),
.INITVAL_2B($sformatf("0x%01280x", init_slice('h2b))),
.INITVAL_2C($sformatf("0x%01280x", init_slice('h2c))),
.INITVAL_2D($sformatf("0x%01280x", init_slice('h2d))),
.INITVAL_2E($sformatf("0x%01280x", init_slice('h2e))),
.INITVAL_2F($sformatf("0x%01280x", init_slice('h2f))),
.INITVAL_30($sformatf("0x%01280x", init_slice('h30))),
.INITVAL_31($sformatf("0x%01280x", init_slice('h31))),
.INITVAL_32($sformatf("0x%01280x", init_slice('h32))),
.INITVAL_33($sformatf("0x%01280x", init_slice('h33))),
.INITVAL_34($sformatf("0x%01280x", init_slice('h34))),
.INITVAL_35($sformatf("0x%01280x", init_slice('h35))),
.INITVAL_36($sformatf("0x%01280x", init_slice('h36))),
.INITVAL_37($sformatf("0x%01280x", init_slice('h37))),
.INITVAL_38($sformatf("0x%01280x", init_slice('h38))),
.INITVAL_39($sformatf("0x%01280x", init_slice('h39))),
.INITVAL_3A($sformatf("0x%01280x", init_slice('h3a))),
.INITVAL_3B($sformatf("0x%01280x", init_slice('h3b))),
.INITVAL_3C($sformatf("0x%01280x", init_slice('h3c))),
.INITVAL_3D($sformatf("0x%01280x", init_slice('h3d))),
.INITVAL_3E($sformatf("0x%01280x", init_slice('h3e))),
.INITVAL_3F($sformatf("0x%01280x", init_slice('h3f))),
.INITVAL_40($sformatf("0x%01280x", init_slice('h40))),
.INITVAL_41($sformatf("0x%01280x", init_slice('h41))),
.INITVAL_42($sformatf("0x%01280x", init_slice('h42))),
.INITVAL_43($sformatf("0x%01280x", init_slice('h43))),
.INITVAL_44($sformatf("0x%01280x", init_slice('h44))),
.INITVAL_45($sformatf("0x%01280x", init_slice('h45))),
.INITVAL_46($sformatf("0x%01280x", init_slice('h46))),
.INITVAL_47($sformatf("0x%01280x", init_slice('h47))),
.INITVAL_48($sformatf("0x%01280x", init_slice('h48))),
.INITVAL_49($sformatf("0x%01280x", init_slice('h49))),
.INITVAL_4A($sformatf("0x%01280x", init_slice('h4a))),
.INITVAL_4B($sformatf("0x%01280x", init_slice('h4b))),
.INITVAL_4C($sformatf("0x%01280x", init_slice('h4c))),
.INITVAL_4D($sformatf("0x%01280x", init_slice('h4d))),
.INITVAL_4E($sformatf("0x%01280x", init_slice('h4e))),
.INITVAL_4F($sformatf("0x%01280x", init_slice('h4f))),
.INITVAL_50($sformatf("0x%01280x", init_slice('h50))),
.INITVAL_51($sformatf("0x%01280x", init_slice('h51))),
.INITVAL_52($sformatf("0x%01280x", init_slice('h52))),
.INITVAL_53($sformatf("0x%01280x", init_slice('h53))),
.INITVAL_54($sformatf("0x%01280x", init_slice('h54))),
.INITVAL_55($sformatf("0x%01280x", init_slice('h55))),
.INITVAL_56($sformatf("0x%01280x", init_slice('h56))),
.INITVAL_57($sformatf("0x%01280x", init_slice('h57))),
.INITVAL_58($sformatf("0x%01280x", init_slice('h58))),
.INITVAL_59($sformatf("0x%01280x", init_slice('h59))),
.INITVAL_5A($sformatf("0x%01280x", init_slice('h5a))),
.INITVAL_5B($sformatf("0x%01280x", init_slice('h5b))),
.INITVAL_5C($sformatf("0x%01280x", init_slice('h5c))),
.INITVAL_5D($sformatf("0x%01280x", init_slice('h5d))),
.INITVAL_5E($sformatf("0x%01280x", init_slice('h5e))),
.INITVAL_5F($sformatf("0x%01280x", init_slice('h5f))),
.INITVAL_60($sformatf("0x%01280x", init_slice('h60))),
.INITVAL_61($sformatf("0x%01280x", init_slice('h61))),
.INITVAL_62($sformatf("0x%01280x", init_slice('h62))),
.INITVAL_63($sformatf("0x%01280x", init_slice('h63))),
.INITVAL_64($sformatf("0x%01280x", init_slice('h64))),
.INITVAL_65($sformatf("0x%01280x", init_slice('h65))),
.INITVAL_66($sformatf("0x%01280x", init_slice('h66))),
.INITVAL_67($sformatf("0x%01280x", init_slice('h67))),
.INITVAL_68($sformatf("0x%01280x", init_slice('h68))),
.INITVAL_69($sformatf("0x%01280x", init_slice('h69))),
.INITVAL_6A($sformatf("0x%01280x", init_slice('h6a))),
.INITVAL_6B($sformatf("0x%01280x", init_slice('h6b))),
.INITVAL_6C($sformatf("0x%01280x", init_slice('h6c))),
.INITVAL_6D($sformatf("0x%01280x", init_slice('h6d))),
.INITVAL_6E($sformatf("0x%01280x", init_slice('h6e))),
.INITVAL_6F($sformatf("0x%01280x", init_slice('h6f))),
.INITVAL_70($sformatf("0x%01280x", init_slice('h70))),
.INITVAL_71($sformatf("0x%01280x", init_slice('h71))),
.INITVAL_72($sformatf("0x%01280x", init_slice('h72))),
.INITVAL_73($sformatf("0x%01280x", init_slice('h73))),
.INITVAL_74($sformatf("0x%01280x", init_slice('h74))),
.INITVAL_75($sformatf("0x%01280x", init_slice('h75))),
.INITVAL_76($sformatf("0x%01280x", init_slice('h76))),
.INITVAL_77($sformatf("0x%01280x", init_slice('h77))),
.INITVAL_78($sformatf("0x%01280x", init_slice('h78))),
.INITVAL_79($sformatf("0x%01280x", init_slice('h79))),
.INITVAL_7A($sformatf("0x%01280x", init_slice('h7a))),
.INITVAL_7B($sformatf("0x%01280x", init_slice('h7b))),
.INITVAL_7C($sformatf("0x%01280x", init_slice('h7c))),
.INITVAL_7D($sformatf("0x%01280x", init_slice('h7d))),
.INITVAL_7E($sformatf("0x%01280x", init_slice('h7e))),
.INITVAL_7F($sformatf("0x%01280x", init_slice('h7f))),
.OUTREG_A("NO_REG"),
.OUTREG_B("NO_REG"),
.ECC_BYTE_SEL("BYTE_EN"),
.GSR("DISABLED"),
.RESETMODE(OPTION_RESETMODE),
.ASYNC_RESET_RELEASE(OPTION_RESETMODE),
) _TECHMAP_REPLACE_ (
.CLK(CLK_C),
.WEA(PORT_A_WR_EN),
.CEA(PORT_A_CLK_EN),
.RSTA(OPTION_RESETMODE == "SYNC" ? PORT_A_RD_SRST : PORT_A_RD_ARST),
.CSA(1'b1),
.ADA(PORT_A_ADDR),
.BENA_N(~PORT_A_WR_BE),
.DIA(PORT_A_WR_DATA),
.DOA(PORT_A_RD_DATA),
.WEB(PORT_B_WR_EN),
.CEB(PORT_B_CLK_EN),
.RSTB(OPTION_RESETMODE == "SYNC" ? PORT_B_RD_SRST : PORT_B_RD_ARST),
.CSB(1'b1),
.BENB_N(~PORT_B_WR_BE),
.ADB(PORT_B_ADDR),
.DIB(PORT_B_WR_DATA),
.DOB(PORT_B_RD_DATA),
);
endmodule

View file

@ -0,0 +1,21 @@
ram huge $__NX_DPSC512K_ {
abits 14;
width 32;
byte 8;
cost 2048;
init no_undef;
port srsw "A" "B" {
clock posedge "C";
clken;
wrbe_separate;
rdwr no_change;
option "RESETMODE" "SYNC" {
rdsrst zero gated_clken;
}
option "RESETMODE" "ASYNC" {
rdarst zero;
}
rdinit zero;
wrtrans all old;
}
}

View file

@ -0,0 +1,23 @@
module $__NEXUS_DPR16X4_ (...);
parameter INIT = 64'b0;
input PORT_W_CLK;
input [3:0] PORT_W_ADDR;
input [3:0] PORT_W_WR_DATA;
input PORT_W_WR_EN;
input [3:0] PORT_R_ADDR;
output [3:0] PORT_R_RD_DATA;
DPR16X4 #(
.INITVAL($sformatf("0x%08x", INIT))
) _TECHMAP_REPLACE_ (
.RAD(PORT_R_ADDR),
.DO(PORT_R_RD_DATA),
.WAD(PORT_W_ADDR),
.DI(PORT_W_WR_DATA),
.WCK(PORT_W_CLK),
.WRE(PORT_W_WR_EN)
);
endmodule

View file

@ -0,0 +1,12 @@
ram distributed $__NEXUS_DPR16X4_ {
abits 4;
width 4;
cost 4;
init no_undef;
prune_rom;
port sw "W" {
clock posedge;
}
port ar "R" {
}
}

View file

@ -0,0 +1,33 @@
function [15:0] parse_init;
input [((2+(16/4))*8)-1:0] init;
reg [7:0] c;
integer i;
begin
for (i = 0; i < (16/4); i = i + 1) begin
c = init[(i * 8) +: 8];
if (c >= "0" && c <= "9")
parse_init[(i * 4) +: 4] = (c - "0");
else if (c >= "A" && c <= "F")
parse_init[(i * 4) +: 4] = (c - "A") + 10;
else if (c >= "a" && c <= "f")
parse_init[(i * 4) +: 4] = (c - "a") + 10;
end
end
endfunction
function [63:0] parse_init_64;
input [((2+(64/4))*8)-1:0] init;
reg [7:0] c;
integer i;
begin
for (i = 0; i < (64/4); i = i + 1) begin
c = init[(i * 8) +: 8];
if (c >= "0" && c <= "9")
parse_init_64[(i * 4) +: 4] = (c - "0");
else if (c >= "A" && c <= "F")
parse_init_64[(i * 4) +: 4] = (c - "A") + 10;
else if (c >= "a" && c <= "f")
parse_init_64[(i * 4) +: 4] = (c - "a") + 10;
end
end
endfunction

View file

@ -35,13 +35,32 @@ struct SynthLatticePass : public ScriptPass
RTLIL::constpad["synth_lattice.abc9.W"] = "300";
}
struct DSPRule {
int a_maxwidth;
int b_maxwidth;
int a_minwidth;
int b_minwidth;
std::string prim;
};
const std::vector<DSPRule> dsp_rules_nexus = {
{36, 36, 22, 22, "$__NX_MUL36X36"},
{36, 18, 22, 10, "$__NX_MUL36X18"},
{18, 18, 10, 4, "$__NX_MUL18X18"},
{18, 18, 4, 10, "$__NX_MUL18X18"},
{ 9, 9, 4, 4, "$__NX_MUL9X9"},
};
const std::vector<DSPRule> dsp_rules_ecp5 = {
{18, 18, 2, 2, "$__MUL18X18"},
};
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" synth_lattice [options]\n");
log("\n");
log("This command runs synthesis for Lattice FPGAs (excluding iCE40 and Nexus).\n");
log("This command runs synthesis for Lattice FPGAs (excluding iCE40).\n");
log("\n");
log(" -top <module>\n");
log(" use the specified module as top module\n");
@ -54,6 +73,8 @@ struct SynthLatticePass : public ScriptPass
log(" - xo2: MachXO2\n");
log(" - xo3: MachXO3L/LF\n");
log(" - xo3d: MachXO3D\n");
log(" - lifcl: CrossLink-NX\n");
log(" - lfd2nx: Certus-NX\n");
//log(" - xo: MachXO (EXPERIMENTAL)\n");
//log(" - pm: Platform Manager (EXPERIMENTAL)\n");
//log(" - pm2: Platform Manager 2 (EXPERIMENTAL)\n");
@ -118,9 +139,13 @@ struct SynthLatticePass : public ScriptPass
log("\n");
log(" -iopad\n");
log(" insert IO buffers\n");
log(" (by default enabled on Nexus FPGAs)\n");
log("\n");
log(" -noiopad\n");
log(" do not insert IO buffers\n");
log("\n");
log(" -nodsp\n");
log(" do not map multipliers to MULT18X18D\n");
log(" do not infer DSP multipliers\n");
log("\n");
log(" -no-rw-check\n");
log(" marks all recognized read ports as \"return don't-care value on\n");
@ -140,7 +165,9 @@ struct SynthLatticePass : public ScriptPass
string top_opt, edif_file, json_file, family;
bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, dff, retime, abc2, abc9, iopad, nodsp, no_rw_check, have_dsp;
bool cmp2softlogic;
string postfix, arith_map, brams_map, dsp_map;
string postfix, arith_map, brams_map, dsp_map, cells_map, map_ram_default, widelut_abc;
bool is_nexus;
std::vector<DSPRule> dsp_rules;
void clear_flags() override
{
@ -168,6 +195,10 @@ struct SynthLatticePass : public ScriptPass
dsp_map = "";
have_dsp = false;
cmp2softlogic = false;
is_nexus = false;
map_ram_default = "";
cells_map = "";
widelut_abc = "4:7";
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
@ -175,6 +206,7 @@ struct SynthLatticePass : public ScriptPass
string run_from, run_to;
bool force_abc9 = false;
bool force_widelut = false;
bool force_iopad = false;
clear_flags();
size_t argidx;
@ -266,6 +298,12 @@ struct SynthLatticePass : public ScriptPass
}
if (args[argidx] == "-iopad") {
iopad = true;
force_iopad = true;
continue;
}
if (args[argidx] == "-noiopad") {
iopad = false;
force_iopad = true;
continue;
}
if (args[argidx] == "-nodsp") {
@ -292,7 +330,9 @@ struct SynthLatticePass : public ScriptPass
arith_map = "_ccu2c";
brams_map = "_16kd";
dsp_map = "_18x18";
dsp_rules = dsp_rules_ecp5;
have_dsp = true;
cells_map = "_trellis";
} else if (family == "xo2" ||
family == "xo3" ||
family == "xo3d" /* ||
@ -300,9 +340,24 @@ struct SynthLatticePass : public ScriptPass
postfix = "_" + family;
arith_map = "_ccu2d";
brams_map = "_8kc";
cells_map = "_trellis";
have_dsp = false;
if (!force_widelut) nowidelut = true;
if (!force_abc9) abc9 = false;
} else if (family == "lifcl" ||
family == "lfd2nx") {
is_nexus = true;
postfix = "_nexus";
arith_map = "_nexus";
brams_map = "_nexus";
dsp_map = "_nexus";
dsp_rules = dsp_rules_nexus;
have_dsp = true;
map_ram_default = " -no-auto-huge";
cells_map = "_nexus";
widelut_abc = "4:5";
if (!force_iopad) iopad = true;
if (!force_abc9) abc9 = false;
/* } else if (family == "xo" ||
family == "pm") {
} else if (family == "xp" ||
@ -366,10 +421,19 @@ struct SynthLatticePass : public ScriptPass
run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
run("opt_expr");
run("opt_clean");
if (have_dsp && !nodsp) {
run("techmap -map +/mul2dsp.v -map +/lattice/dsp_map" + dsp_map + ".v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=$__MUL18X18", "(unless -nodsp)");
run("chtype -set $mul t:$__soft_mul", "(unless -nodsp)");
if (help_mode) {
run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)");
run("techmap -map +/lattice/dsp_map" + dsp_map + ".v", "(unless -nodsp)");
} else if (have_dsp && !nodsp) {
for (const auto &rule : dsp_rules) {
run(stringf("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=%d -D DSP_B_MAXWIDTH=%d -D DSP_A_MINWIDTH=%d -D DSP_B_MINWIDTH=%d -D DSP_NAME=%s",
rule.a_maxwidth, rule.b_maxwidth, rule.a_minwidth, rule.b_minwidth, rule.prim.c_str()));
run("chtype -set $mul t:$__soft_mul");
}
run("techmap -map +/lattice/dsp_map" + dsp_map + ".v");
}
run("alumacc");
run("opt");
run("memory -nomap" + no_rw_check_opt);
@ -378,15 +442,20 @@ struct SynthLatticePass : public ScriptPass
if (check_label("map_ram"))
{
std::string args = "";
std::string args = map_ram_default;
if (nobram)
args += " -no-auto-block";
if (nolutram)
args += " -no-auto-distributed";
if (help_mode)
args += " [-no-auto-block] [-no-auto-distributed]";
run("memory_libmap -lib +/lattice/lutrams.txt -lib +/lattice/brams" + brams_map + ".txt" + args, "(-no-auto-block if -nobram, -no-auto-distributed if -nolutram)");
run("techmap -map +/lattice/lutrams_map.v -map +/lattice/brams_map" + brams_map + ".v");
if (!is_nexus) {
run("memory_libmap -lib +/lattice/lutrams" + cells_map + ".txt -lib +/lattice/brams" + brams_map + ".txt" + args, "(-no-auto-block if -nobram, -no-auto-distributed if -nolutram)");
run("techmap -map +/lattice/lutrams_map" + cells_map + ".v -map +/lattice/brams_map" + brams_map + ".v");
} else {
run("memory_libmap -lib +/lattice/lutrams" + cells_map + ".txt -lib +/lattice/brams" + brams_map + ".txt -lib +/lattice/lrams_nexus.txt" + args, "(-no-auto-block if -nobram, -no-auto-distributed if -nolutram)");
run("techmap -map +/lattice/lutrams_map" + cells_map + ".v -map +/lattice/brams_map" + brams_map + ".v -map +/lattice/lrams_map_nexus.v");
}
}
if (check_label("map_ffram"))
@ -415,27 +484,37 @@ struct SynthLatticePass : public ScriptPass
if (check_label("map_ffs"))
{
run("opt_clean");
std::string dfflegalize_args = " -cell $_DFF_?_ 01 -cell $_DFF_?P?_ r -cell $_SDFF_?P?_ r";
if (help_mode) {
dfflegalize_args += " [-cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r]";
} else if (!nodffe) {
dfflegalize_args += " -cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r";
}
if (help_mode) {
dfflegalize_args += " [-cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x] [-cell $_DLATCH_?_ x]";
} else if (asyncprld) {
dfflegalize_args += " -cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x";
if (!is_nexus) {
std::string dfflegalize_args = " -cell $_DFF_?_ 01 -cell $_DFF_?P?_ r -cell $_SDFF_?P?_ r";
if (help_mode) {
dfflegalize_args += " [-cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r]";
} else if (!nodffe) {
dfflegalize_args += " -cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r";
}
if (help_mode) {
dfflegalize_args += " [-cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x] [-cell $_DLATCH_?_ x]";
} else if (asyncprld) {
dfflegalize_args += " -cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x";
} else {
dfflegalize_args += " -cell $_DLATCH_?_ x";
}
run("dfflegalize" + dfflegalize_args, "($_ALDFF_*_ only if -asyncprld, $_DLATCH_* only if not -asyncprld, $_*DFFE_* only if not -nodffe)");
} else {
dfflegalize_args += " -cell $_DLATCH_?_ x";
}
run("dfflegalize" + dfflegalize_args, "($_ALDFF_*_ only if -asyncprld, $_DLATCH_* only if not -asyncprld, $_*DFFE_* only if not -nodffe)");
std::string dfflegalize_args = " -cell $_DFF_P_ 01 -cell $_DFF_PP?_ r -cell $_SDFF_PP?_ r -cell $_DLATCH_?_ x";
if (help_mode) {
dfflegalize_args += " [-cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r]";
} else if (!nodffe) {
dfflegalize_args += " -cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r";
}
run("dfflegalize" + dfflegalize_args, "($_*DFFE_* only if not -nodffe)");
}
run("opt_merge");
if ((abc9 && dff) || help_mode)
run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF*", "(only if -abc9 and -dff)");
run("techmap -D NO_LUT -map +/lattice/cells_map.v");
run("techmap -D NO_LUT -map +/lattice/cells_map" + cells_map + ".v");
run("opt_expr -undriven -mux_undef");
run("simplemap");
run("lattice_gsr");
if (!is_nexus) run("lattice_gsr");
run("attrmvcp -copy -attr syn_useioff");
run("opt_clean");
}
@ -466,7 +545,7 @@ struct SynthLatticePass : public ScriptPass
if (nowidelut)
abc_args += " -lut 4";
else
abc_args += " -lut 4:7";
abc_args += " -lut " + widelut_abc;
if (dff)
abc_args += " -dff";
run("abc" + abc_args);
@ -476,8 +555,14 @@ struct SynthLatticePass : public ScriptPass
if (check_label("map_cells"))
{
run("techmap -map +/lattice/cells_map.v");
run("opt_lut_ins -tech lattice");
run("techmap -map +/lattice/cells_map" + cells_map + ".v");
if (is_nexus) {
// This is needed for Radiant, but perhaps not optimal for nextpnr...
run("setundef -zero");
run("hilomap -singleton -hicell VHI Z -locell VLO Z");
} else {
run("opt_lut_ins -tech lattice");
}
run("clean");
}
@ -504,6 +589,33 @@ struct SynthLatticePass : public ScriptPass
}
} SynthLatticePass;
struct SynthNexusPass : public Pass
{
SynthNexusPass() : Pass("synth_nexus", "synthesis for Nexus FPGAs") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" synth_nexus [options]\n");
log("\n");
log("This command runs synthesis for Nexus FPGAs.\n");
log("\n");
log("This is a wrapper pass, for details take a look at help message for synth_lattice.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
args[0] = "synth_lattice";
args.insert(args.begin()+1, std::string());
args.insert(args.begin()+1, std::string());
args[1] = "-family";
args[2] = "lifcl";
Pass::call(design, args);
}
} SynthNexusPass;
struct SynthEcp5Pass : public Pass
{
SynthEcp5Pass() : Pass("synth_ecp5", "synthesis for ECP5 FPGAs") { }