Merge pull request #2397 from daveshah1/nexus

synth_nexus: Initial implementation
This commit is contained in:
Miodrag Milanović 2020-10-19 11:20:56 +02:00 committed by GitHub
commit ac0bd2ffc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 12528 additions and 0 deletions

View File

@ -789,6 +789,7 @@ test: $(TARGETS) $(EXTRA_TARGETS)
+cd tests/arch/anlogic && bash run-test.sh $(SEEDOPT)
+cd tests/arch/gowin && bash run-test.sh $(SEEDOPT)
+cd tests/arch/intel_alm && bash run-test.sh $(SEEDOPT)
+cd tests/arch/nexus && bash run-test.sh $(SEEDOPT)
+cd tests/rpc && bash run-test.sh
+cd tests/memfile && bash run-test.sh
+cd tests/verilog && bash run-test.sh

View File

@ -0,0 +1,14 @@
OBJS += techlibs/nexus/synth_nexus.o
$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_map.v))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_sim.v))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/parse_init.vh))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_xtra.v))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/lutrams_map.v))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/lutrams.txt))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams_init.vh))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams_map.v))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams.txt))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/arith_map.v))
$(eval $(call add_share_file,share/nexus,techlibs/nexus/latches_map.v))

View File

@ -0,0 +1,99 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xen <claire@symbioticeda.com>
* Copyright (C) 2018 David Shah <dave@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]) || (((i == 0) ? CI : CO[i-1]) && (AA[i] || BB[i]));
if (i+1 < Y_WIDTH) begin
assign CO[i+1] = (AA[i+1] && BB[i+1]) || (CO[i] && (AA[i+1] || BB[i+1]));
assign Y[i+1] = Y1[i];
end
end endgenerate
assign X = AA ^ BB;
endmodule

60
techlibs/nexus/brams.txt Normal file
View File

@ -0,0 +1,60 @@
bram $__NX_PDP16K
init 1
abits 9 @a9d36
dbits 36 @a9d36
abits 10 @a10d18
dbits 18 @a10d18
abits 11 @a11d9
dbits 9 @a11d9
abits 12 @a12d4
dbits 4 @a12d4
abits 13 @a13d2
dbits 2 @a13d2
abits 14 @a14d1
dbits 1 @a14d1
groups 2
ports 1 1
wrmode 1 0
enable 4 1 @a9d36
enable 2 1 @a10d18
enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1
transp 0 0
clocks 2 3
clkpol 2 3
endbram
match $__NX_PDP16K
# implicitly requested RAM or ROM
attribute !syn_ramstyle syn_ramstyle=auto
attribute !syn_romstyle syn_romstyle=auto
attribute !ram_block
attribute !rom_block
attribute !logic_block
min bits 2048
min efficiency 5
shuffle_enable A
or_next_if_better
endmatch
match $__NX_PDP16K
# explicitly requested RAM
attribute syn_ramstyle=block_ram ram_block
attribute !syn_romstyle
attribute !rom_block
attribute !logic_block
min wports 1
shuffle_enable A
or_next_if_better
endmatch
match $__NX_PDP16K
# explicitly requested ROM
attribute syn_romstyle=ebr rom_block
attribute !syn_ramstyle
attribute !ram_block
attribute !logic_block
max wports 0
shuffle_enable A
endmatch

View File

@ -0,0 +1,64 @@
.INITVAL_00($sformatf("0x%080x", permute_init(INIT[0 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_01($sformatf("0x%080x", permute_init(INIT[1 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_02($sformatf("0x%080x", permute_init(INIT[2 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_03($sformatf("0x%080x", permute_init(INIT[3 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_04($sformatf("0x%080x", permute_init(INIT[4 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_05($sformatf("0x%080x", permute_init(INIT[5 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_06($sformatf("0x%080x", permute_init(INIT[6 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_07($sformatf("0x%080x", permute_init(INIT[7 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_08($sformatf("0x%080x", permute_init(INIT[8 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_09($sformatf("0x%080x", permute_init(INIT[9 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_0A($sformatf("0x%080x", permute_init(INIT[10 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_0B($sformatf("0x%080x", permute_init(INIT[11 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_0C($sformatf("0x%080x", permute_init(INIT[12 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_0D($sformatf("0x%080x", permute_init(INIT[13 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_0E($sformatf("0x%080x", permute_init(INIT[14 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_0F($sformatf("0x%080x", permute_init(INIT[15 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_10($sformatf("0x%080x", permute_init(INIT[16 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_11($sformatf("0x%080x", permute_init(INIT[17 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_12($sformatf("0x%080x", permute_init(INIT[18 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_13($sformatf("0x%080x", permute_init(INIT[19 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_14($sformatf("0x%080x", permute_init(INIT[20 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_15($sformatf("0x%080x", permute_init(INIT[21 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_16($sformatf("0x%080x", permute_init(INIT[22 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_17($sformatf("0x%080x", permute_init(INIT[23 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_18($sformatf("0x%080x", permute_init(INIT[24 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_19($sformatf("0x%080x", permute_init(INIT[25 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_1A($sformatf("0x%080x", permute_init(INIT[26 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_1B($sformatf("0x%080x", permute_init(INIT[27 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_1C($sformatf("0x%080x", permute_init(INIT[28 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_1D($sformatf("0x%080x", permute_init(INIT[29 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_1E($sformatf("0x%080x", permute_init(INIT[30 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_1F($sformatf("0x%080x", permute_init(INIT[31 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_20($sformatf("0x%080x", permute_init(INIT[32 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_21($sformatf("0x%080x", permute_init(INIT[33 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_22($sformatf("0x%080x", permute_init(INIT[34 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_23($sformatf("0x%080x", permute_init(INIT[35 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_24($sformatf("0x%080x", permute_init(INIT[36 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_25($sformatf("0x%080x", permute_init(INIT[37 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_26($sformatf("0x%080x", permute_init(INIT[38 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_27($sformatf("0x%080x", permute_init(INIT[39 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_28($sformatf("0x%080x", permute_init(INIT[40 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_29($sformatf("0x%080x", permute_init(INIT[41 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_2A($sformatf("0x%080x", permute_init(INIT[42 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_2B($sformatf("0x%080x", permute_init(INIT[43 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_2C($sformatf("0x%080x", permute_init(INIT[44 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_2D($sformatf("0x%080x", permute_init(INIT[45 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_2E($sformatf("0x%080x", permute_init(INIT[46 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_2F($sformatf("0x%080x", permute_init(INIT[47 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_30($sformatf("0x%080x", permute_init(INIT[48 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_31($sformatf("0x%080x", permute_init(INIT[49 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_32($sformatf("0x%080x", permute_init(INIT[50 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_33($sformatf("0x%080x", permute_init(INIT[51 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_34($sformatf("0x%080x", permute_init(INIT[52 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_35($sformatf("0x%080x", permute_init(INIT[53 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_36($sformatf("0x%080x", permute_init(INIT[54 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_37($sformatf("0x%080x", permute_init(INIT[55 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_38($sformatf("0x%080x", permute_init(INIT[56 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_39($sformatf("0x%080x", permute_init(INIT[57 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_3A($sformatf("0x%080x", permute_init(INIT[58 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_3B($sformatf("0x%080x", permute_init(INIT[59 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_3C($sformatf("0x%080x", permute_init(INIT[60 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_3D($sformatf("0x%080x", permute_init(INIT[61 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_3E($sformatf("0x%080x", permute_init(INIT[62 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE]))),
.INITVAL_3F($sformatf("0x%080x", permute_init(INIT[63 * INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])))

115
techlibs/nexus/brams_map.v Normal file
View File

@ -0,0 +1,115 @@
module \$__NX_PDP16K (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter CFG_ABITS = 9;
parameter CFG_DBITS = 36;
parameter CFG_ENABLE_A = 4;
parameter CLKPOL2 = 1;
parameter CLKPOL3 = 1;
parameter [18431:0] INIT = 18432'b0;
parameter _TECHMAP_BITS_CONNMAP_ = 8;
parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_CLK2_ = 0;
parameter [_TECHMAP_BITS_CONNMAP_-1:0] _TECHMAP_CONNMAP_CLK3_ = 0;
input CLK2;
input CLK3;
input [CFG_ABITS-1:0] A1ADDR;
input [CFG_DBITS-1:0] A1DATA;
input [CFG_ENABLE_A-1:0] A1EN;
input [CFG_ABITS-1:0] B1ADDR;
output [CFG_DBITS-1:0] B1DATA;
input B1EN;
// Address is left justified, in x18 and above lower bits are byte enables
localparam A_SHIFT =
(CFG_DBITS == 36) ? 5 :
(CFG_DBITS == 18) ? 4 :
(CFG_DBITS == 9) ? 3 :
(CFG_DBITS == 4) ? 2 :
(CFG_DBITS == 2) ? 1 :
0;
// Different primitives needed for single vs dual clock case
localparam SINGLE_CLOCK = (_TECHMAP_CONNMAP_CLK2_ == _TECHMAP_CONNMAP_CLK3_);
localparam WIDTH = $sformatf("X%d", CFG_DBITS);
wire [13:0] ra, wa;
wire [35:0] rd, wd;
assign ra = {B1ADDR, {A_SHIFT{1'b1}}};
generate
if (CFG_ENABLE_A > 1)
assign wa = {A1ADDR, {(A_SHIFT-CFG_ENABLE_A){1'b1}}, A1EN};
else
assign wa = {A1ADDR, {A_SHIFT{1'b1}}};
endgenerate
assign wd = A1DATA;
assign B1DATA = rd[CFG_DBITS-1:0];
wire wck, rck;
generate
if (CLKPOL2)
assign wck = CLK2;
else
INV wck_inv_i (.A(CLK2), .Z(wck));
if (CLKPOL3)
assign rck = CLK3;
else
INV wck_inv_i (.A(CLK3), .Z(rck));
endgenerate
wire we = |A1EN;
localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 4) ? 256 : 288;
function [319:0] permute_init;
input [INIT_CHUNK_SIZE-1:0] chunk;
integer i;
begin
if (CFG_DBITS <= 4) begin
for (i = 0; i < 32; i = i + 1'b1)
permute_init[i * 10 +: 10] = {2'b00, chunk[i * 8 +: 8]};
end else begin
for (i = 0; i < 32; i = i + 1'b1)
permute_init[i * 10 +: 10] = {1'b0, chunk[i * 9 +: 9]};
end
end
endfunction
generate
if (SINGLE_CLOCK) begin
PDPSC16K #(
.DATA_WIDTH_W(WIDTH),
.DATA_WIDTH_R(WIDTH),
.OUTREG("BYPASSED"),
.ECC("DISABLED"),
.GSR("DISABLED"),
`include "brams_init.vh"
) _TECHMAP_REPLACE_ (
.CLK(wck), .RST(1'b0),
.DI(wd), .ADW(wa), .CEW(we), .CSW(3'b111),
.ADR(ra), .DO(rd), .CER(B1EN), .CSR(3'b111)
);
end else begin
PDP16K #(
.DATA_WIDTH_W(WIDTH),
.DATA_WIDTH_R(WIDTH),
.OUTREG("BYPASSED"),
.ECC("DISABLED"),
.GSR("DISABLED"),
`include "brams_init.vh"
) _TECHMAP_REPLACE_ (
.CLKW(wck), .CLKR(rck), .RST(1'b0),
.DI(wd), .ADW(wa), .CEW(we), .CSW(3'b111),
.ADR(ra), .DO(rd), .CER(B1EN), .CSR(3'b111)
);
end
endgenerate
endmodule

106
techlibs/nexus/cells_map.v Normal file
View File

@ -0,0 +1,106 @@
// 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
module \$__NX_TINOUTPAD (input I, OE, output O, inout B);
BB _TECHMAP_REPLACE_ (.I(I), .O(O), .T(~OE), .B(B));
endmodule
module \$__NX_TOUTPAD (input I, OE, output O);
OBZ _TECHMAP_REPLACE_ (.I(I), .O(), .T(~OE), .O(O));
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

379
techlibs/nexus/cells_sim.v Normal file
View File

@ -0,0 +1,379 @@
(* abc9_lut=1, lib_whitebox *)
module LUT4(input A, B, C, D, output Z);
parameter INIT = "0x0000";
`include "parse_init.vh"
localparam initp = parse_init(INIT);
wire [7:0] s3 = D ? initp[15:8] : initp[7:0];
wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
assign Z = A ? s1[1] : s1[0];
// Per-input delay differences are considered 'interconnect'
// so not known yet
specify
(A => Z) = 233;
(B => Z) = 233;
(C => Z) = 233;
(D => Z) = 233;
endspecify
endmodule
// This is a placeholder for ABC9 to extract the area/delay
// cost of 5-input LUTs and is not intended to be instantiated
(* abc9_lut=2 *)
module \$__ABC9_LUT5 (input SEL, D, C, B, A, output Z);
specify
(SEL => Z) = 171;
(D => Z) = 303;
(C => Z) = 311;
(B => Z) = 309;
(A => Z) = 306;
endspecify
endmodule
// Two LUT4s and MUX2
module WIDEFN9(input A0, B0, C0, D0, A1, B1, C1, D1, SEL, output Z);
parameter INIT0 = "0x0000";
parameter INIT1 = "0x0000";
wire z0, z1;
LUT4 #(.INIT(INIT0)) lut4_0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(z0));
LUT4 #(.INIT(INIT1)) lut4_1 (.A(A1), .B(B1), .C(C1), .D(D1), .Z(z1));
assign Z = SEL ? z1 : z0;
endmodule
(* abc9_box, lib_whitebox *)
module INV(input A, output Z);
assign Z = !A;
specify
(A => Z) = 10;
endspecify
endmodule
// Bidirectional IO buffer
module BB(input T, I, output O,
(* iopad_external_pin *) inout B);
assign B = T ? 1'bz : O;
assign I = B;
endmodule
// Input buffer
module IB(
(* iopad_external_pin *) input I,
output O);
assign O = I;
endmodule
// Output buffer
module OB(input I,
(* iopad_external_pin *) output O);
assign O = I;
endmodule
// Output buffer with tristate
module OBZ(input I, T,
(* iopad_external_pin *) output O);
assign O = T ? 1'bz : I;
endmodule
// Constants
module VLO(output Z);
assign Z = 1'b0;
endmodule
module VHI(output Z);
assign Z = 1'b1;
endmodule
// Vendor flipflops
// (all have active high clock, enable and set/reset - use INV to invert)
// Async preset
(* abc9_box, lib_whitebox *)
module FD1P3BX(input D, CK, SP, PD, output reg Q);
parameter GSR = "DISABLED";
initial Q = 1'b1;
always @(posedge CK or posedge PD)
if (PD)
Q <= 1'b1;
else if (SP)
Q <= D;
specify
$setup(D, posedge CK, 0);
$setup(SP, posedge CK, 212);
$setup(PD, posedge CK, 224);
`ifndef YOSYS
if (PD) (posedge CLK => (Q : 1)) = 0;
`else
if (PD) (PD => Q) = 0; // Technically, this should be an edge sensitive path
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
if (!PD && SP) (posedge CK => (Q : D)) = 336;
endspecify
endmodule
// Async clear
(* abc9_box, lib_whitebox *)
module FD1P3DX(input D, CK, SP, CD, output reg Q);
parameter GSR = "DISABLED";
initial Q = 1'b0;
always @(posedge CK or posedge CD)
if (CD)
Q <= 1'b0;
else if (SP)
Q <= D;
specify
$setup(D, posedge CK, 0);
$setup(SP, posedge CK, 212);
$setup(CD, posedge CK, 224);
`ifndef YOSYS
if (CD) (posedge CLK => (Q : 0)) = 0;
`else
if (CD) (CD => Q) = 0; // Technically, this should be an edge sensitive path
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
if (!CD && SP) (posedge CK => (Q : D)) = 336;
endspecify
endmodule
// Sync clear
(* abc9_flop, lib_whitebox *)
module FD1P3IX(input D, CK, SP, CD, output reg Q);
parameter GSR = "DISABLED";
initial Q = 1'b0;
always @(posedge CK)
if (CD)
Q <= 1'b0;
else if (SP)
Q <= D;
specify
$setup(D, posedge CK, 0);
$setup(SP, posedge CK, 212);
$setup(CD, posedge CK, 224);
if (!CD && SP) (posedge CK => (Q : D)) = 336;
endspecify
endmodule
// Sync preset
(* abc9_flop, lib_whitebox *)
module FD1P3JX(input D, CK, SP, PD, output reg Q);
parameter GSR = "DISABLED";
initial Q = 1'b1;
always @(posedge CK)
if (PD)
Q <= 1'b1;
else if (SP)
Q <= D;
specify
$setup(D, posedge CK, 0);
$setup(SP, posedge CK, 212);
$setup(PD, posedge CK, 224);
if (!PD && SP) (posedge CK => (Q : D)) = 336;
endspecify
endmodule
// LUT4 with LUT3 tap for CCU2 use only
(* lib_whitebox *)
module LUT4_3(input A, B, C, D, output Z, Z3);
parameter INIT = "0x0000";
`include "parse_init.vh"
localparam initp = parse_init(INIT);
wire [7:0] s3 = D ? initp[15:8] : initp[7:0];
wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
assign Z = A ? s1[1] : s1[0];
wire [3:0] s2_3 = C ? initp[ 7:4] : initp[3:0];
wire [1:0] s1_3 = B ? s2_3[ 3:2] : s2_3[1:0];
assign Z3 = A ? s1_3[1] : s1_3[0];
endmodule
// Carry primitive (incoporating two LUTs)
(* abc9_box, lib_whitebox *)
module CCU2(
(* abc9_carry *) input CIN,
input A1, B1, C1, D1, A0, B0, C0, D0,
output S1, S0,
(* abc9_carry *) output COUT);
parameter INJECT = "YES";
parameter INIT0 = "0x0000";
parameter INIT1 = "0x1111";
localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
wire LUT3_0, LUT4_0, LUT3_1, LUT4_1, carry_0;
LUT4_3 #(.INIT(INIT0)) lut0 (.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0), .Z3(LUT3_0));
LUT4_3 #(.INIT(INIT1)) lut1 (.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1), .Z3(LUT3_1));
assign S0 = LUT4_0 ^ (CIN & ~inject_p);
assign carry_0 = LUT4_0 ? CIN : (LUT3_0 & ~inject_p);
assign S1 = LUT4_1 ^ (carry_0 & ~inject_p);
assign COUT = LUT4_1 ? carry_0 : (LUT3_1 & ~inject_p);
specify
(A0 => S0) = 233;
(B0 => S0) = 233;
(C0 => S0) = 233;
(D0 => S0) = 233;
(CIN => S0) = 228;
(A0 => S1) = 481;
(B0 => S1) = 481;
(C0 => S1) = 481;
(D0 => S1) = 481;
(A1 => S1) = 233;
(B1 => S1) = 233;
(C1 => S1) = 233;
(D1 => S1) = 233;
(CIN => S1) = 307;
(A0 => COUT) = 347;
(B0 => COUT) = 347;
(C0 => COUT) = 347;
(D0 => COUT) = 347;
(A1 => COUT) = 347;
(B1 => COUT) = 347;
(C1 => COUT) = 347;
(D1 => COUT) = 347;
(CIN => COUT) = 59;
endspecify
endmodule
// Packed flipflop
module OXIDE_FF(input CLK, LSR, CE, DI, M, output reg Q);
parameter GSR = "ENABLED";
parameter [127:0] CEMUX = "1";
parameter CLKMUX = "CLK";
parameter LSRMUX = "LSR";
parameter REGDDR = "DISABLED";
parameter SRMODE = "LSR_OVER_CE";
parameter REGSET = "RESET";
parameter [127:0] LSRMODE = "LSR";
wire muxce;
generate
case (CEMUX)
"1": assign muxce = 1'b1;
"0": assign muxce = 1'b0;
"INV": assign muxce = ~CE;
default: assign muxce = CE;
endcase
endgenerate
wire muxlsr = (LSRMUX == "INV") ? ~LSR : LSR;
wire muxclk = (CLKMUX == "INV") ? ~CLK : CLK;
wire srval;
generate
if (LSRMODE == "PRLD")
assign srval = M;
else
assign srval = (REGSET == "SET") ? 1'b1 : 1'b0;
endgenerate
initial Q = srval;
generate
if (REGDDR == "ENABLED") begin
if (SRMODE == "ASYNC") begin
always @(posedge muxclk, negedge muxclk, posedge muxlsr)
if (muxlsr)
Q <= srval;
else if (muxce)
Q <= DI;
end else begin
always @(posedge muxclk, negedge muxclk)
if (muxlsr)
Q <= srval;
else if (muxce)
Q <= DI;
end
end else begin
if (SRMODE == "ASYNC") begin
always @(posedge muxclk, posedge muxlsr)
if (muxlsr)
Q <= srval;
else if (muxce)
Q <= DI;
end else begin
always @(posedge muxclk)
if (muxlsr)
Q <= srval;
else if (muxce)
Q <= DI;
end
end
endgenerate
endmodule
// Packed combinational logic (for post-pnr sim)
module OXIDE_COMB(
input A, B, C, D, // LUT inputs
input SEL, // mux select input
input F1, // output from LUT 1 for mux
input FCI, // carry input
input WAD0, WAD1, WAD2, WAD3, // LUTRAM write address inputs
input WD, // LUTRAM write data input
input WCK, WRE, // LUTRAM write clock and enable
output F, // LUT/carry output
output OFX // mux output
);
parameter MODE = "LOGIC"; // LOGIC, CCU2, DPRAM
parameter [15:0] INIT = 16'h0000;
parameter INJECT = "YES";
localparam inject_p = (INJECT == "YES") ? 1'b1 : 1'b0;
reg [15:0] lut = INIT;
wire [7:0] s3 = D ? INIT[15:8] : INIT[7:0];
wire [3:0] s2 = C ? s3[ 7:4] : s3[3:0];
wire [1:0] s1 = B ? s2[ 3:2] : s2[1:0];
wire Z = A ? s1[1] : s1[0];
wire [3:0] s2_3 = C ? INIT[ 7:4] : INIT[3:0];
wire [1:0] s1_3 = B ? s2_3[ 3:2] : s2_3[1:0];
wire Z3 = A ? s1_3[1] : s1_3[0];
generate
if (MODE == "DPRAM") begin
always @(posedge WCK)
if (WRE)
lut[{WAD3, WAD2, WAD1, WAD0}] <= WD;
end
if (MODE == "CCU2") begin
assign F = Z ^ (FCI & ~inject_p);
assign FCO = Z ? FCI : (Z3 & ~inject_p);
end else begin
assign F = Z;
end
endgenerate
assign OFX = SEL ? F1 : F;
endmodule
// LUTRAM
module DPR16X4(
input [3:0] RAD, DI, WAD,
input WRE, WCK,
output [3:0] DO
);
parameter INITVAL = "0x0000000000000000";
`include "parse_init.vh"
localparam [63:0] parsed_init = parse_init_64(INITVAL);
reg [3:0] mem[0:15];
integer i;
initial begin
for (i = 0; i < 15; i++)
mem[i] = parsed_init[i * 4 +: 4];
end
always @(posedge WCK)
if (WRE)
mem[WAD] <= DI;
assign DO = mem[RAD];
endmodule

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_xtra.v', 'w') as f:
f.write('// Created by cells_xtra.py from Lattice models\n')
f.write('\n')
f.write(out.getvalue())

10630
techlibs/nexus/cells_xtra.v Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
module \$_DLATCH_N_ (E, D, Q);
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
input E, D;
output Q = !E ? D : Q;
endmodule
module \$_DLATCH_P_ (E, D, Q);
wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
input E, D;
output Q = E ? D : Q;
endmodule

View File

@ -0,0 +1,26 @@
bram $__NEXUS_DPR16X4
init 1
abits 4
dbits 4
groups 2
ports 1 1
wrmode 0 1
enable 0 1
transp 0 0
clocks 0 1
clkpol 0 2
endbram
# The syn_* attributes are described in:
# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx
attr_icase 1
match $__NEXUS_DPR16X4
attribute !syn_ramstyle syn_ramstyle=auto syn_ramstyle=distributed
attribute !syn_romstyle syn_romstyle=auto
attribute !ram_block
attribute !rom_block
attribute !logic_block
make_outreg
min wports 1
endmatch

View File

@ -0,0 +1,34 @@
module \$__NEXUS_DPR16X4 (CLK1, A1ADDR, A1DATA, B1ADDR, B1DATA, B1EN);
parameter [63:0] INIT = 64'b0;
parameter CLKPOL2 = 1;
input CLK1;
input [3:0] A1ADDR;
output [3:0] A1DATA;
input [3:0] B1ADDR;
input [3:0] B1DATA;
input B1EN;
wire wck;
generate
if (CLKPOL2)
assign wck = CLK1;
else
INV wck_inv_i (.A(CLK1), .Z(wck));
endgenerate
DPR16X4 #(
.INITVAL($sformatf("0x%08x", INIT))
) _TECHMAP_REPLACE_ (
.RAD(A1ADDR),
.DO(A1DATA),
.WAD(B1ADDR),
.DI(B1DATA),
.WCK(CLK1),
.WRE(B1EN)
);
endmodule

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

@ -0,0 +1,372 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2020 David Shah <dave@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.
*
*/
#include "kernel/register.h"
#include "kernel/celltypes.h"
#include "kernel/rtlil.h"
#include "kernel/log.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct SynthNexusPass : public ScriptPass
{
SynthNexusPass() : ScriptPass("synth_nexus", "synthesis for Lattice Nexus FPGAs") { }
void on_register() override
{
RTLIL::constpad["synth_nexus.abc9.W"] = "300";
}
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 Lattice Nexus FPGAs.\n");
log("\n");
log(" -top <module>\n");
log(" use the specified module as top module\n");
log("\n");
log(" -family <device>\n");
log(" run synthesis for the specified Nexus device\n");
log(" supported values: lifcl, lfd2nx\n");
log("\n");
log(" -json <file>\n");
log(" write the design to the specified JSON file. writing of an output file\n");
log(" is omitted if this parameter is not specified.\n");
log("\n");
log(" -vm <file>\n");
log(" write the design to the specified structural Verilog file. writing of\n");
log(" an output file is omitted if this parameter is not specified.\n");
log("\n");
log(" -run <from_label>:<to_label>\n");
log(" only run the commands between the labels (see below). an empty\n");
log(" from label is synonymous to 'begin', and empty to label is\n");
log(" synonymous to the end of the command list.\n");
log("\n");
log(" -noflatten\n");
log(" do not flatten design before synthesis\n");
log("\n");
log(" -dff\n");
log(" run 'abc'/'abc9' with -dff option\n");
log("\n");
log(" -retime\n");
log(" run 'abc' with '-dff -D 1' options\n");
log("\n");
log(" -noccu2\n");
log(" do not use CCU2 cells in output netlist\n");
log("\n");
log(" -nodffe\n");
log(" do not use flipflops with CE in output netlist\n");
log("\n");
log(" -nobram\n");
log(" do not use block RAM cells in output netlist\n");
log("\n");
log(" -nolutram\n");
log(" do not use LUT RAM cells in output netlist\n");
log("\n");
log(" -nowidelut\n");
log(" do not use PFU muxes to implement LUTs larger than LUT4s\n");
log("\n");
log(" -noiopad\n");
log(" do not insert IO buffers\n");
log("\n");
log(" -abc9\n");
log(" use new ABC9 flow (EXPERIMENTAL)\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
log("\n");
}
string top_opt, json_file, vm_file, family;
bool noccu2, nodffe, nobram, nolutram, nowidelut, noiopad, flatten, dff, retime, abc9;
void clear_flags() override
{
top_opt = "-auto-top";
family = "lifcl";
json_file = "";
vm_file = "";
noccu2 = false;
nodffe = false;
nobram = false;
nolutram = false;
nowidelut = false;
noiopad = false;
flatten = true;
dff = false;
retime = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
string run_from, run_to;
clear_flags();
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
if (args[argidx] == "-top" && argidx+1 < args.size()) {
top_opt = "-top " + args[++argidx];
continue;
}
if (args[argidx] == "-json" && argidx+1 < args.size()) {
json_file = args[++argidx];
continue;
}
if (args[argidx] == "-vm" && argidx+1 < args.size()) {
vm_file = args[++argidx];
continue;
}
if (args[argidx] == "-run" && argidx+1 < args.size()) {
size_t pos = args[argidx+1].find(':');
if (pos == std::string::npos)
break;
run_from = args[++argidx].substr(0, pos);
run_to = args[argidx].substr(pos+1);
continue;
}
if ((args[argidx] == "-family") && argidx+1 < args.size()) {
family = args[++argidx];
continue;
}
if (args[argidx] == "-flatten") {
flatten = true;
continue;
}
if (args[argidx] == "-noflatten") {
flatten = false;
continue;
}
if (args[argidx] == "-dff") {
dff = true;
continue;
}
if (args[argidx] == "-retime") {
retime = true;
continue;
}
if (args[argidx] == "-noccu2") {
noccu2 = true;
continue;
}
if (args[argidx] == "-nodffe") {
nodffe = true;
continue;
}
if (args[argidx] == "-nobram") {
nobram = true;
continue;
}
if (args[argidx] == "-nolutram") {
nolutram = true;
continue;
}
if (args[argidx] == "-nowidelut") {
nowidelut = true;
continue;
}
if (args[argidx] == "-noiopad") {
noiopad = true;
continue;
}
if (args[argidx] == "-abc9") {
abc9 = true;
continue;
}
break;
}
extra_args(args, argidx, design);
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
if (abc9 && retime)
log_cmd_error("-retime option not currently compatible with -abc9!\n");
log_header(design, "Executing SYNTH_NEXUS pass.\n");
log_push();
run_script(design, run_from, run_to);
log_pop();
}
void script() override
{
if (family != "lifcl" && family != "lfd2nx")
log_cmd_error("Invalid Nexus -family setting: '%s'.\n", family.c_str());
if (check_label("begin"))
{
run("read_verilog -lib -specify +/nexus/cells_sim.v +/nexus/cells_xtra.v");
run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
}
if (check_label("coarse"))
{
run("proc");
if (flatten || help_mode)
run("flatten");
run("tribuf -logic");
run("deminout");
run("opt_expr");
run("opt_clean");
run("check");
run("opt -nodffe -nosdff");
run("fsm");
run("opt");
run("wreduce");
run("peepopt");
run("opt_clean");
run("share");
run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
run("opt_expr");
run("opt_clean");
run("alumacc");
run("opt");
run("memory -nomap");
run("opt_clean");
}
if (!nobram && check_label("map_bram", "(skip if -nobram)"))
{
run("memory_bram -rules +/nexus/brams.txt");
run("setundef -zero -params t:$__NX_PDP16K");
run("techmap -map +/nexus/brams_map.v");
}
if (!nolutram && check_label("map_lutram", "(skip if -nolutram)"))
{
run("memory_bram -rules +/nexus/lutrams.txt");
run("setundef -zero -params t:$__NEXUS_DPR16X4");
run("techmap -map +/nexus/lutrams_map.v");
}
if (check_label("map_ffram"))
{
run("opt -fast -mux_undef -undriven -fine");
run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block "
"-attr syn_ramstyle=auto -attr syn_ramstyle=registers "
"-attr syn_romstyle=auto -attr syn_romstyle=logic");
run("opt -undriven -fine");
}
if (check_label("map_gates"))
{
if (noccu2)
run("techmap");
else
run("techmap -map +/techmap.v -map +/nexus/arith_map.v");
if (help_mode || !noiopad)
run("iopadmap -bits -outpad OB I:O -inpad IB O:I -toutpad $__NX_TOUTPAD OE:I:O -tinoutpad $__NX_TINOUTPAD OE:O:I:B A:top", "(skip if '-noiopad')");
run("opt -fast");
if (retime || help_mode)
run("abc -dff -D 1", "(only if -retime)");
}
if (check_label("map_ffs"))
{
run("opt_clean");
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)");
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 +/nexus/cells_map.v");
run("opt_expr -undriven -mux_undef");
run("simplemap");
run("attrmvcp -copy -attr syn_useioff");
run("opt_clean");
}
if (check_label("map_luts"))
{
run("techmap -map +/nexus/latches_map.v");
if (abc9) {
std::string abc9_opts;
if (nowidelut)
abc9_opts += " -maxlut 4";
std::string k = "synth_nexus.abc9.W";
if (active_design && active_design->scratchpad.count(k))
abc9_opts += stringf(" -W %s", active_design->scratchpad_get_string(k).c_str());
else
abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str());
if (nowidelut)
abc9_opts += " -maxlut 4";
if (dff)
abc9_opts += " -dff";
run("abc9" + abc9_opts);
} else {
std::string abc_args = " -dress";
if (nowidelut)
abc_args += " -lut 4";
else
abc_args += " -lut 4:5";
if (dff)
abc_args += " -dff";
run("abc" + abc_args);
}
run("clean");
}
if (check_label("map_cells"))
{
run("techmap -map +/nexus/cells_map.v");
// This is needed for Radiant, but perhaps not optimal for nextpnr...
run("setundef -zero");
run("hilomap -singleton -hicell VHI Z -locell VLO Z");
run("clean");
}
if (check_label("check"))
{
run("autoname");
run("hierarchy -check");
run("stat");
run("check -noinit");
}
if (check_label("json"))
{
if (!json_file.empty() || help_mode)
run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
}
if (check_label("vm"))
{
if (!vm_file.empty() || help_mode)
run(stringf("write_verilog %s", help_mode ? "<file-name>" : vm_file.c_str()));
}
}
} SynthNexusPass;
PRIVATE_NAMESPACE_END

2
tests/arch/nexus/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/*.log
/run-test.mk

View File

@ -0,0 +1,21 @@
read_verilog ../common/add_sub.v
hierarchy -top top
proc
design -save orig
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
stat
select -assert-count 10 t:LUT4
select -assert-none t:IB t:OB t:VLO t:LUT4 %% t:* %D
design -load orig
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus -abc9 # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
stat
select -assert-count 6 t:LUT4
select -assert-count 4 t:WIDEFN9
select -assert-none t:IB t:OB t:VLO t:LUT4 t:WIDEFN9 %% t:* %D

44
tests/arch/nexus/adffs.ys Normal file
View File

@ -0,0 +1,44 @@
read_verilog ../common/adffs.v
design -save read
hierarchy -top adff
proc
equiv_opt -async2sync -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd adff # Constrain all select calls below inside the top module
stat
select -assert-count 1 t:FD1P3DX
select -assert-none t:FD1P3DX t:IB t:OB t:VLO t:VHI %% t:* %D
design -load read
hierarchy -top adffn
proc
equiv_opt -async2sync -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd adffn # Constrain all select calls below inside the top module
stat
select -assert-count 1 t:FD1P3DX
select -assert-count 1 t:INV
select -assert-none t:FD1P3DX t:INV t:LUT4 t:IB t:OB t:VLO t:VHI %% t:* %D
design -load read
hierarchy -top dffs
proc
equiv_opt -async2sync -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dffs # Constrain all select calls below inside the top module
stat
select -assert-count 1 t:FD1P3IX
select -assert-count 1 t:LUT4
select -assert-none t:FD1P3IX t:LUT4 t:IB t:OB t:VLO t:VHI %% t:* %D
design -load read
hierarchy -top ndffnr
proc
equiv_opt -async2sync -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd ndffnr # Constrain all select calls below inside the top module
stat
select -assert-count 1 t:FD1P3IX
select -assert-count 2 t:INV
select -assert-none t:FD1P3IX t:INV t:LUT4 t:IB t:OB t:VLO t:VHI %% t:* %D

View File

@ -0,0 +1,18 @@
read_verilog ../common/blockram.v
design -save read
# Check that we use the right dual and single clock variants
chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 18 sync_ram_sdp
synth_nexus -top sync_ram_sdp
cd sync_ram_sdp
select -assert-count 1 t:PDPSC16K
select -assert-none t:PDPSC16K t:INV t:IB t:OB t:VLO t:VHI %% t:* %D
design -reset
read_verilog blockram_dc.v
chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 18 sync_ram_sdp_dc
synth_nexus -top sync_ram_sdp_dc
cd sync_ram_sdp_dc
select -assert-count 1 t:PDP16K
select -assert-none t:PDP16K t:INV t:IB t:OB t:VLO t:VHI %% t:* %D

View File

@ -0,0 +1,25 @@
`default_nettype none
module sync_ram_sdp_dc #(parameter DATA_WIDTH=8, ADDRESS_WIDTH=10)
(input wire clkw, clkr, write_enable,
input wire [DATA_WIDTH-1:0] data_in,
input wire [ADDRESS_WIDTH-1:0] address_in_r, address_in_w,
output wire [DATA_WIDTH-1:0] data_out);
localparam WORD = (DATA_WIDTH-1);
localparam DEPTH = (2**ADDRESS_WIDTH-1);
reg [WORD:0] data_out_r;
reg [WORD:0] memory [0:DEPTH];
always @(posedge clkw) begin
if (write_enable)
memory[address_in_w] <= data_in;
end
always @(posedge clkr) begin
data_out_r <= memory[address_in_r];
end
assign data_out = data_out_r;
endmodule // sync_ram_sdp_dc

View File

@ -0,0 +1,11 @@
read_verilog ../common/counter.v
hierarchy -top top
proc
flatten
equiv_opt -assert -multiclock -map +/nexus/cells_sim.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
stat
select -assert-count 5 t:CCU2
select -assert-count 8 t:FD1P3DX
select -assert-none t:CCU2 t:FD1P3DX t:IB t:OB t:VLO t:VHI %% t:* %D

19
tests/arch/nexus/dffs.ys Normal file
View File

@ -0,0 +1,19 @@
read_verilog ../common/dffs.v
design -save read
hierarchy -top dff
proc
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dff # Constrain all select calls below inside the top module
select -assert-count 1 t:FD1P3IX
select -assert-none t:FD1P3IX t:IB t:OB t:VHI t:VLO %% t:* %D
design -load read
hierarchy -top dffe
proc
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dffe # Constrain all select calls below inside the top module
select -assert-count 1 t:FD1P3IX
select -assert-none t:FD1P3IX t:IB t:OB t:VHI t:VLO %% t:* %D

19
tests/arch/nexus/fsm.ys Normal file
View File

@ -0,0 +1,19 @@
read_verilog ../common/fsm.v
hierarchy -top fsm
proc
flatten
equiv_opt -run :prove -map +/nexus/cells_sim.v synth_nexus
miter -equiv -make_assert -flatten gold gate miter
sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd fsm # Constrain all select calls below inside the top module
stat
select -assert-max 1 t:INV
select -assert-max 2 t:LUT4
select -assert-max 6 t:WIDEFN9
select -assert-count 6 t:FD1P3IX
select -assert-none t:LUT4 t:FD1P3IX t:WIDEFN9 t:INV t:IB t:OB t:VLO t:VHI %% t:* %D

View File

@ -0,0 +1,8 @@
read_verilog ../common/logic.v
hierarchy -top top
proc
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
select -assert-count 8 t:LUT4
select -assert-none t:LUT4 t:INV t:IB t:OB t:VLO t:VHI %% t:* %D

View File

@ -0,0 +1,19 @@
read_verilog ../common/lutram.v
hierarchy -top lutram_1w1r
proc
memory -nomap
equiv_opt -run :prove -map +/nexus/cells_sim.v synth_nexus
memory
opt -full
miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter
design -load postopt
cd lutram_1w1r
stat
select -assert-count 8 t:WIDEFN9
select -assert-count 16 t:LUT4
select -assert-count 8 t:DPR16X4
select -assert-count 36 t:FD1P3IX
select -assert-none t:DPR16X4 t:FD1P3IX t:WIDEFN9 t:LUT4 t:INV t:IB t:OB t:VLO t:VHI %% t:* %D

28
tests/arch/nexus/mul.ys Normal file
View File

@ -0,0 +1,28 @@
read_verilog ../common/mul.v
hierarchy -top top
proc
design -save read
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
select -assert-count 7 t:CCU2
select -assert-max 5 t:WIDEFN9
select -assert-max 62 t:LUT4
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:CCU2 t:WIDEFN9 %% t:* %D
design -load read
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus -abc9
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
stat
select -assert-count 7 t:CCU2
select -assert-max 12 t:WIDEFN9
select -assert-max 58 t:LUT4
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:CCU2 t:WIDEFN9 %% t:* %D

43
tests/arch/nexus/mux.ys Normal file
View File

@ -0,0 +1,43 @@
read_verilog ../common/mux.v
design -save read
hierarchy -top mux2
proc
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux2 # Constrain all select calls below inside the top module
select -assert-count 1 t:LUT4
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:WIDEFN9 %% t:* %D
design -load read
hierarchy -top mux4
proc
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux4 # Constrain all select calls below inside the top module
select -assert-count 1 t:WIDEFN9
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:WIDEFN9 %% t:* %D
design -load read
hierarchy -top mux8
proc
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux8 # Constrain all select calls below inside the top module
select -assert-count 4 t:LUT4
select -assert-count 1 t:WIDEFN9
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:WIDEFN9 %% t:* %D
design -load read
hierarchy -top mux16
proc
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux16 # Constrain all select calls below inside the top module
select -assert-min 11 t:LUT4
select -assert-max 12 t:LUT4
select -assert-count 1 t:WIDEFN9
select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:WIDEFN9 %% t:* %D

View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -e
{
echo "all::"
for x in *.ys; do
echo "all:: run-$x"
echo "run-$x:"
echo " @echo 'Running $x..'"
echo " @../../../yosys -ql ${x%.ys}.log -w 'Yosys has only limited support for tri-state logic at the moment.' $x"
done
for s in *.sh; do
if [ "$s" != "run-test.sh" ]; then
echo "all:: run-$s"
echo "run-$s:"
echo " @echo 'Running $s..'"
echo " @bash $s"
fi
done
} > run-test.mk
exec ${MAKE:-make} -f run-test.mk

View File

@ -0,0 +1,9 @@
read_verilog ../common/shifter.v
hierarchy -top top
proc
flatten
equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
select -assert-count 8 t:FD1P3IX
select -assert-none t:FD1P3IX t:WIDEFN9 t:INV t:IB t:OB t:VLO t:VHI %% t:* %D

View File

@ -0,0 +1,12 @@
read_verilog ../common/tribuf.v
hierarchy -top tristate
proc
tribuf
flatten
synth
equiv_opt -assert -map +/nexus/cells_sim.v -map +/simcells.v synth_nexus # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd tristate # Constrain all select calls below inside the top module
select -assert-count 1 t:OBZ
select -assert-count 1 t:INV
select -assert-none t:OBZ t:INV t:IB t:OB t:VLO t:VHI %% t:* %D