Skip to content

Commit

Permalink
Add synth_nanoxplore for NanoXplore FPGAs
Browse files Browse the repository at this point in the history
  • Loading branch information
Ravenslofty committed Sep 4, 2023
1 parent 2f901a8 commit 1c1f19b
Show file tree
Hide file tree
Showing 33 changed files with 26,671 additions and 0 deletions.
11 changes: 11 additions & 0 deletions techlibs/nanoxplore/Makefile.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

OBJS += techlibs/nanoxplore/synth_nanoxplore.o

# Techmap
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/abc9_map.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/abc9_model.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/abc9_unmap.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/arith_map.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_map.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/cells_sim.v))
$(eval $(call add_share_file,share/nanoxplore,techlibs/nanoxplore/drams.txt))
22 changes: 22 additions & 0 deletions techlibs/nanoxplore/abc9_map.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// This file exists to map purely-synchronous flops to ABC9 flops, while
// mapping flops with asynchronous-clear as boxes, this is because ABC9
// doesn't support asynchronous-clear flops in sequential synthesis.

module NX_DFF(input I, CK, L, R, output O);

parameter dff_ctxt = 1'bx;
parameter dff_edge = 1'b0;
parameter dff_init = 1'b0;
parameter dff_load = 1'b0;
parameter dff_sync = 1'b0;
parameter dff_type = 1'b0;

localparam RESETLESS = !dff_init;
localparam SYNC_RESET = dff_init && dff_sync;

if (RESETLESS || SYNC_RESET) begin
$__NX_DFF_SYNCONLY #(.dff_ctxt(dff_ctxt), .dff_edge(dff_edge), .dff_init(dff_init), .dff_load(dff_load), .dff_type(dff_type)) _TECHMAP_REPLACE_ (.I(I), .CK(CK), .L(L), .R(R), .O(O));
end else
wire _TECHMAP_FAIL_ = 1;

endmodule
30 changes: 30 additions & 0 deletions techlibs/nanoxplore/abc9_model.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// This is a purely-synchronous flop, that ABC9 can use for sequential synthesis.
(* abc9_flop, lib_whitebox *)
module \$__NX_DFF_SYNCONLY (input I, CK, L, R, output reg O);

parameter dff_ctxt = 1'bx;
parameter dff_edge = 1'b0;
parameter dff_init = 1'b0;
parameter dff_load = 1'b0;
parameter dff_type = 1'b0;

specify
(posedge CK => (O : I)) = (247, 281);
$setup(I, posedge CK, 232);
$setup(L, posedge CK, 231);
$setup(R, posedge CK, 209);
endspecify

initial begin
O = dff_ctxt;
end

wire clock = CK ^ dff_edge;
wire load = (dff_type == 2) ? (dff_load ? L : 1'bx) : dff_type;
wire sync_reset = dff_init && R;

always @(posedge clock)
if (sync_reset) O <= load;
else O <= I;

endmodule
9 changes: 9 additions & 0 deletions techlibs/nanoxplore/abc9_unmap.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// This is a purely-synchronous flop, that ABC9 can use for sequential synthesis.
module \$__NX_DFF_SYNCONLY (input I, CK, L, R, output O);
parameter dff_ctxt = 1'bx;
parameter dff_edge = 1'b0;
parameter dff_init = 1'b0;
parameter dff_load = 1'b0;
parameter dff_type = 1'b0;
NX_DFF #(.dff_ctxt(dff_ctxt), .dff_edge(dff_edge), .dff_init(dff_init), .dff_load(dff_load), .dff_sync(1'b1), .dff_type(dff_type)) _TECHMAP_REPLACE_ (.I(I), .CK(CK), .L(L), .R(R), .O(O));
endmodule
71 changes: 71 additions & 0 deletions techlibs/nanoxplore/arith_map.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
`default_nettype none

(* techmap_celltype = "$alu" *)
module _80_ecp5_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 <= 2;

(* 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_up4;
input integer N;
begin
round_up4 = ((N + 3) / 4) * 4;
end
endfunction

localparam Y_WIDTH4 = round_up4(Y_WIDTH);

(* force_downto *)
wire [Y_WIDTH4-1:0] AA = A_buf;
(* force_downto *)
wire [Y_WIDTH4-1:0] BB = BI ? ~B_buf : B_buf;
(* force_downto *)
wire [Y_WIDTH4-1:0] BX = B_buf;
(* force_downto *)
wire [Y_WIDTH4:0] C = {CO, CI};
(* force_downto *)
wire [Y_WIDTH4-1:0] FCO, Y1;

genvar i;
generate for (i = 0; i < Y_WIDTH4; i = i + 4) begin:slice
NX_CY cy_i (
.CI(C[i]),
.A1(AA[i]), .A2(AA[i+1]), .A3(AA[i+2]), .A4(AA[i+3]),
.B1(BB[i]), .B2(BB[i+1]), .B3(BB[i+2]), .B4(BB[i+3]),
.S1(Y1[i]), .S2(Y1[i+1]), .S3(Y1[i+2]), .S4(Y1[i+3]),
.CO(FCO[i])
);

assign CO[i] = (AA[i] && BB[i]) || (C[i] && (AA[i] || BB[i]));
if (i+1 < Y_WIDTH)
assign CO[i+1] = (AA[i+1] && BB[i+1]) || (C[i+1] && (AA[i+1] || BB[i+1]));
if (i+2 < Y_WIDTH)
assign CO[i+2] = (AA[i+2] && BB[i+2]) || (C[i+2] && (AA[i+2] || BB[i+2]));
if (i+3 < Y_WIDTH)
assign CO[i+3] = FCO[i];

end endgenerate

assign X = AA ^ BB;
assign Y = Y1[Y_WIDTH-1:0];
endmodule
81 changes: 81 additions & 0 deletions techlibs/nanoxplore/cells_map.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
`default_nettype none

module \$lut (A, Y);
parameter WIDTH = 0;
parameter LUT = 0;

(* force_downto *)
input [WIDTH-1:0] A;
output Y;

generate
if (WIDTH == 1) begin
localparam [15:0] INIT = {{8{LUT[1]}}, {8{LUT[0]}}};
NX_LUT #(.lut_table(INIT)) _TECHMAP_REPLACE_ (.O(Y),
.I1(1'b0), .I2(1'b0), .I3(1'b0), .I4(A[0]));
end else
if (WIDTH == 2) begin
localparam [15:0] INIT = {{4{LUT[3]}}, {4{LUT[2]}}, {4{LUT[1]}}, {4{LUT[0]}}};
NX_LUT #(.lut_table(INIT)) _TECHMAP_REPLACE_ (.O(Y),
.I1(1'b0), .I2(1'b0), .I3(A[0]), .I4(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]}}};
NX_LUT #(.lut_table(INIT)) _TECHMAP_REPLACE_ (.O(Y),
.I1(1'b0), .I2(A[0]), .I3(A[1]), .I4(A[2]));
end else
if (WIDTH == 4) begin
NX_LUT #(.lut_table(LUT)) _TECHMAP_REPLACE_ (.O(Y),
.I1(A[0]), .I2(A[1]), .I3(A[2]), .I4(A[3]));
end else begin
wire _TECHMAP_FAIL_ = 1;
end
endgenerate
endmodule

(* techmap_celltype = "$_DFF_[NP]P[01]_" *)
module dff(input D, C, R, output Q);
parameter _TECHMAP_CELLTYPE = "$_DFF_PP1_";
localparam dff_edge = _TECHMAP_CELLTYPE[6*8 +: 8] == "N";
localparam dff_type = _TECHMAP_CELLTYPE[8*8 +: 8] == "1";
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
NX_DFF #(.dff_ctxt(1'b0), .dff_edge(dff_edge), .dff_init(1'b1), .dff_load(1'b0), .dff_sync(1'b0), .dff_type(dff_type)) _TECHMAP_REPLACE_ (.I(D), .CK(C), .L(1'b0), .R(R), .O(Q));
endmodule

(* techmap_celltype = "$_ALDFF_[NP]P_" *)
module aldff(input D, C, L, AD, output Q);
parameter _TECHMAP_CELLTYPE = "$_ALDFF_PP_";
localparam dff_edge = _TECHMAP_CELLTYPE[8*8 +: 8] == "N";
wire _TECHMAP_REMOVEINIT_Q_ = 1'b1;
NX_DFF #(.dff_ctxt(1'b0), .dff_edge(dff_edge), .dff_init(1'b1), .dff_load(1'b1), .dff_sync(1'b0), .dff_type(2)) _TECHMAP_REPLACE_ (.I(D), .CK(C), .L(AD), .R(L), .O(Q));
endmodule

module \$_SDFF_PP0_ (input D, C, R, output Q);
NX_DFF #(.dff_ctxt(1'b0), .dff_edge(1'b0), .dff_init(1'b1), .dff_load(1'b0), .dff_sync(1'b1), .dff_type(1'b0)) _TECHMAP_REPLACE_ (.I(D), .CK(C), .L(1'b0), .R(R), .O(Q));
endmodule

module \$_SDFF_PP1_ (input D, C, R, output Q);
NX_DFF #(.dff_ctxt(1'b0), .dff_edge(1'b0), .dff_init(1'b1), .dff_load(1'b0), .dff_sync(1'b1), .dff_type(1'b1)) _TECHMAP_REPLACE_ (.I(D), .CK(C), .L(1'b0), .R(R), .O(Q));
endmodule

module \$_SDFF_NP0_ (input D, C, R, output Q);
NX_DFF #(.dff_ctxt(1'b0), .dff_edge(1'b1), .dff_init(1'b1), .dff_load(1'b0), .dff_sync(1'b1), .dff_type(1'b0)) _TECHMAP_REPLACE_ (.I(D), .CK(C), .L(1'b0), .R(R), .O(Q));
endmodule

module \$_SDFF_NP1_ (input D, C, R, output Q);
NX_DFF #(.dff_ctxt(1'b0), .dff_edge(1'b1), .dff_init(1'b1), .dff_load(1'b0), .dff_sync(1'b1), .dff_type(1'b1)) _TECHMAP_REPLACE_ (.I(D), .CK(C), .L(1'b0), .R(R), .O(Q));
endmodule


module $__NX_XRFB_64x18_ (input PORT_W_CLK, input [5:0] PORT_W_ADDR, PORT_R_ADDR, input [17:0] PORT_W_WR_DATA, input PORT_W_WR_EN, output [17:0] PORT_R_RD_DATA);
parameter INIT = 1152'bx;
parameter PORT_W_CLK_POL = 1'b1;
NX_XRFB_64x18 #(.mem_ctxt(INIT), .wck_edge(~PORT_W_CLK_POL)) _TECHMAP_REPLACE_ (.WCK(PORT_W_CLK), .I(PORT_W_WR_DATA), .RA(PORT_R_ADDR), .WA(PORT_W_ADDR), .WE(PORT_W_WR_EN), .WEA(1'b1), .O(PORT_R_RD_DATA));
endmodule


module $__NX_XRFB_32x36_ (input PORT_W_CLK, input [4:0] PORT_W_ADDR, PORT_R_ADDR, input [35:0] PORT_W_WR_DATA, input PORT_W_WR_EN, output [35:0] PORT_R_RD_DATA);
parameter INIT = 1152'bx;
parameter PORT_W_CLK_POL = 1'b1;
NX_XRFB_32x36 #(.mem_ctxt(INIT), .wck_edge(~PORT_W_CLK_POL)) _TECHMAP_REPLACE_ (.WCK(PORT_W_CLK), .I(PORT_W_WR_DATA), .RA(PORT_R_ADDR), .WA(PORT_W_ADDR), .WE(PORT_W_WR_EN), .WEA(1'b1), .O(PORT_R_RD_DATA));
endmodule
145 changes: 145 additions & 0 deletions techlibs/nanoxplore/cells_sim.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
(* abc9_lut=1 *)
module NX_LUT(input I1, I2, I3, I4, output O);

parameter lut_table = 16'h0000;

specify
(I1 => O) = (117, 129);
(I2 => O) = (112, 125);
(I3 => O) = (61, 89);
(I4 => O) = (61, 81);
endspecify

wire [7:0] s1 = I4 ? lut_table[15:8] : lut_table[7:0];
wire [3:0] s2 = I3 ? s1[7:4] : s1[3:0];
wire [1:0] s3 = I2 ? s2[3:2] : s2[1:0];
assign O = I1 ? s3[1] : s3[0];

endmodule

(* abc9_box, lib_whitebox *)
module NX_DFF(input I, CK, L, R, output reg O);

parameter dff_ctxt = 1'bx;
parameter dff_edge = 1'b0;
parameter dff_init = 1'b0;
parameter dff_load = 1'b0;
parameter dff_sync = 1'b0;
parameter dff_type = 1'b0;

specify
(posedge CK => (O : I)) = (247, 281);
if (!dff_sync && dff_init && R) (R => O) = 0;
if (!dff_sync && dff_init && dff_load && R) (L => O) = 0;
$setup(I, posedge CK, 232);
$setup(L, posedge CK, 231);
$setup(R, posedge CK, 209);
endspecify

initial begin
O = dff_ctxt;
end

wire clock = CK ^ dff_edge;
wire load = (dff_type == 2) ? (dff_load ? L : 1'bx) : dff_type;
wire async_reset = !dff_sync && dff_init && R;
wire sync_reset = dff_sync && dff_init && R;

always @(posedge clock, posedge async_reset)
if (async_reset) O <= load;
else if (sync_reset) O <= load;
else O <= I;

endmodule

(* abc9_box, lib_whitebox *)
module NX_CY(input A1, A2, A3, A4, B1, B2, B3, B4, (* abc9_carry *) input CI, output S1, S2, S3, S4, (* abc9_carry *) output CO);

specify
(A1 => CO) = (206, 266);
(A2 => CO) = (210, 282);
(A3 => CO) = (181, 253);
(A4 => CO) = (137, 211);
(B1 => CO) = (152, 205);
(B2 => CO) = (154, 214);
(B3 => CO) = (106, 166);
(B4 => CO) = ( 89, 149);
(CI => CO) = ( 40, 113);
(A1 *> {S4, S3, S2, S1}) = (314, 325);
(A2 *> {S4, S3, S2}) = (236, 248);
(A3 *> {S4, S3}) = (226, 238);
(A4 => S4) = (166, 179);
(B1 *> {S4, S3, S2, S1}) = (262, 274);
(B2 *> {S4, S3, S2}) = (184, 195);
(B3 *> {S4, S3}) = (156, 166);
(B4 => S4) = (105, 117);
(CI *> {S4, S3, S2, S1}) = (268, 291);
endspecify

assign {CO, S4, S3, S2, S1} = {A4, A3, A2, A1} + {B4, B3, B2, B1} + CI;

endmodule

(* abc9_box, lib_whitebox *)
module NX_XRFB_64x18(input WCK, input [17:0] I, input [5:0] RA, WA, input WE, WEA, output [17:0] O);

parameter wck_edge = 1'b0;
parameter mem_ctxt = 1152'b0;

specify
(WCK *> O) = 474;
(RA *> O) = 2111; // good enough for now
$setup(I, posedge WCK, 0);
$setup(WA, posedge WCK, 0);
$setup(WE, posedge WCK, 0);
endspecify

reg [17:0] mem [63:0];

integer i;
initial begin
for (i = 0; i < 64; i = i + 1)
mem[i] = mem_ctxt[18*i +: 18];
end

wire clock = WCK ^ wck_edge;

always @(posedge clock)
if (WE && WEA)
mem[WA] <= I;

assign O = mem[RA];

endmodule

(* abc9_box, lib_whitebox *)
module NX_XRFB_32x36(input WCK, input [35:0] I, input [4:0] RA, WA, input WE, WEA, output [35:0] O);

parameter wck_edge = 1'b0;
parameter mem_ctxt = 1152'b0;

specify
(WCK *> O) = 474;
(RA *> O) = 2111; // good enough for now
$setup(I, posedge WCK, 0);
$setup(WA, posedge WCK, 0);
$setup(WE, posedge WCK, 0);
endspecify

reg [35:0] mem [31:0];

integer i;
initial begin
for (i = 0; i < 32; i = i + 1)
mem[i] = mem_ctxt[36*i +: 36];
end

wire clock = WCK ^ wck_edge;

always @(posedge clock)
if (WE && WEA)
mem[WA] <= I;

assign O = mem[RA];

endmodule
Loading

0 comments on commit 1c1f19b

Please sign in to comment.