Merge pull request #1226 from lnis-uofu/xt_adder

Enable Adder mapping and validation on FPGA architecture using hard adders
This commit is contained in:
tangxifan 2023-06-20 18:25:25 -07:00 committed by GitHub
commit 8d62ac1ec0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 134 additions and 173 deletions

View File

@ -0,0 +1,48 @@
# Yosys synthesis script for ${TOP_MODULE}
# Read verilog files
read_verilog ${READ_VERILOG_OPTIONS} ${VERILOG_FILES}
# Technology mapping
hierarchy -top ${TOP_MODULE}
proc
techmap -D NO_LUT -map +/adff2dff.v
# Synthesis
flatten
opt_expr
opt_clean
check
opt -nodffe -nosdff
fsm
opt -nodffe -nosdff
wreduce
peepopt
opt_clean
# Map Adders
techmap -map +/techmap.v -map ${YOSYS_ADDER_MAP_VERILOG}
opt -fast -nodffe -nosdff
opt_expr
opt_merge
opt_clean
opt -nodffe -nosdff
#
memory -nomap
opt_clean
opt -fast -full -nodffe -nosdff
memory_map
opt -full -nodffe -nosdff
techmap
opt -fast -nodffe -nosdff
clean
# LUT mapping
abc -lut ${LUT_SIZE}
# Check
#synth -run check
# Clean and output blif
opt_clean -purge
write_blif ${OUTPUT_BLIF}

View File

@ -1,15 +1,15 @@
//---------------------------------------
// 1-bit adder
//---------------------------------------
(* abc9_box, lib_whitebox *)
module adder(
input cin,
input a,
input b,
output cout,
output sumout );
assign sumout = a ^ b ^ cin;
assign cout = (a & b) | ((a | b) & cin);
output sumout,
output cout,
input a,
input b,
input cin
);
assign sumout = a ^ b ^ cin;
assign cout = (a & b) | ((a | b) & cin);
endmodule

View File

@ -1,164 +1,67 @@
//////////////////////////
// arithmetic //
//////////////////////////
// Arithmetic units: adder
// Adapt from: https://github.com/chipsalliance/yosys-f4pga-plugins/blob/0ad1af26a29243a9e76379943d735e119dcd0cc6/ql-qlf-plugin/qlf_k6n10/cells_sim.v
// Many thanks to F4PGA for their contribution
module \$alu (A, B, CI, BI, X, Y, CO);
(* techmap_celltype = "$alu" *)
module _80_quicklogic_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;
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B;
output [Y_WIDTH:0] X, Y;
input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B;
output [Y_WIDTH-1:0] X, Y;
input CI, BI;
output [Y_WIDTH:0] CO;
input CI, BI;
output [Y_WIDTH-1:0] CO;
wire [Y_WIDTH-1:0] AA, BB;
wire [1024:0] _TECHMAP_DO_ = "splitnets CARRY; clean";
wire [1024:0] _TECHMAP_DO_ = "splitnets CARRY; clean";
generate
if (A_SIGNED && B_SIGNED) begin:BLOCK1
assign AA = $signed(A), BB = BI ? ~$signed(B) : $signed(B);
end else begin:BLOCK2
assign AA = $unsigned(A), BB = BI ? ~$unsigned(B) : $unsigned(B);
end
endgenerate
(* 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));
wire [Y_WIDTH: 0 ] CARRY;
assign CARRY[0] = CI;
(* force_downto *)
wire [Y_WIDTH-1:0] AA = A_buf;
(* force_downto *)
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
wire [Y_WIDTH: 0 ] CARRY;
genvar i;
generate for (i = 0; i < Y_WIDTH - 1; i = i+1) begin:gen3
adder my_adder (
.cin (CARRY[i]),
.cout (CARRY[i+1]),
.a (AA[i]),
.b (BB[i]),
.sumout (Y[i])
);
end endgenerate
assign CO[Y_WIDTH-1:0] = CARRY[Y_WIDTH:1];
// Due to VPR limitations regarding IO connexion to carry chain,
// we generate the carry chain input signal using an intermediate adder
// since we can connect a & b from io pads, but not cin & cout
generate
adder intermediate_adder (
.cin ( ),
.cout (CARRY[0]),
.a (CI ),
.b (CI ),
.sumout ( )
);
generate if ((Y_WIDTH -1) % 20 == 0) begin:gen4
assign Y[Y_WIDTH-1] = CARRY[Y_WIDTH-1];
end else begin:gen5
adder my_adder (
.cin (CARRY[Y_WIDTH - 1]),
.cout (CARRY[Y_WIDTH]),
.a (1'b0),
.b (1'b0),
.sumout (Y[Y_WIDTH -1])
);
end
endgenerate
endmodule
adder first_adder (
.cin (CARRY[0]),
.cout (CARRY[1]),
.a (AA[0] ),
.b (BB[0] ),
.sumout (Y[0] )
);
endgenerate
//---------------------------------------------------------
module \$fa (A, B, C, X, Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B;
input C;
output [Y_WIDTH:0] X, Y;
wire [Y_WIDTH-1:0] AA, BB;
wire [1024:0] _TECHMAP_DO_ = "splitnets CARRY; clean";
generate
if (A_SIGNED && B_SIGNED) begin:BLOCK1
assign AA = $signed(A), BB = $signed(B);
end else begin:BLOCK2
assign AA = $unsigned(A), BB = $unsigned(B);
end
endgenerate
wire [Y_WIDTH: 0 ] CARRY;
assign CARRY[0] = C;
genvar i;
generate for (i = 0; i < Y_WIDTH - 1; i = i+1) begin:gen3
adder my_adder (
.cin (CARRY[i]),
.cout (CARRY[i+1]),
.a (AA[i]),
.b (BB[i]),
.sumout (Y[i])
);
end endgenerate
generate if ((Y_WIDTH -1) % 20 == 0) begin:gen4
assign Y[Y_WIDTH-1] = CARRY[Y_WIDTH-1];
end else begin:gen5
adder my_adder (
.cin (CARRY[Y_WIDTH - 1]),
.cout (CARRY[Y_WIDTH]),
.a (1'b0),
.b (1'b0),
.sumout (Y[Y_WIDTH -1])
);
end
endgenerate
endmodule
//---------------------------------------------------------
module \$add (A, B, Y);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;
input [A_WIDTH-1:0] A;
input [B_WIDTH-1:0] B;
output [Y_WIDTH:0] Y;
wire [Y_WIDTH-1:0] AA, BB;
wire [1024:0] _TECHMAP_DO_ = "splitnets CARRY; clean";
generate
if (A_SIGNED && B_SIGNED) begin:BLOCK1
assign AA = $signed(A), BB = $signed(B);
end else begin:BLOCK2
assign AA = $unsigned(A), BB = $unsigned(B);
end
endgenerate
wire [Y_WIDTH: 0 ] CARRY;
assign CARRY[0] = 1'b0;
genvar i;
generate for (i = 0; i < Y_WIDTH - 1; i = i+1) begin:gen3
adder my_adder (
.cin (CARRY[i]),
.cout (CARRY[i+1]),
.a (AA[i]),
.b (BB[i]),
.sumout (Y[i])
);
end endgenerate
generate if ((Y_WIDTH -1) % 20 == 0) begin:gen4
assign Y[Y_WIDTH-1] = CARRY[Y_WIDTH-1];
end else begin:gen5
adder my_adder (
.cin (CARRY[Y_WIDTH - 1]),
.cout (CARRY[Y_WIDTH]),
.a (1'b0),
.b (1'b0),
.sumout (Y[Y_WIDTH -1])
);
end
endgenerate
endmodule
genvar i;
generate for (i = 1; i < Y_WIDTH ; i = i+1) begin:gen3
adder my_adder (
.cin (CARRY[i] ),
.cout (CARRY[i+1]),
.a (AA[i] ),
.b (BB[i] ),
.sumout (Y[i] )
);
end endgenerate
assign X = AA ^ BB;
endmodule

View File

@ -294,6 +294,7 @@ def generate_each_task_actions(taskname):
yosys_params = [
"read_verilog_options",
"yosys_args",
"yosys_adder_map_verilog",
"yosys_bram_map_rules",
"yosys_bram_map_verilog",
"yosys_cell_sim_verilog",

View File

@ -0,0 +1,4 @@
<pin_constraints>
<!-- Intend to be empty -->
</pin_constraints>

View File

@ -9,29 +9,34 @@
[GENERAL]
run_engine=openfpga_shell
power_tech_file = ${PATH:OPENFPGA_PATH}/openfpga_flow/tech/PTM_45nm/45nm.xml
power_analysis = true
power_analysis = false
spice_output=false
verilog_output=true
timeout_each_job = 20*60
fpga_flow=vpr_blif
fpga_flow=yosys_vpr
[OpenFPGA_SHELL]
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/fix_device_example_script.openfpga
openfpga_shell_template=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_shell_scripts/example_without_ace_script.openfpga
openfpga_arch_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_arch/k6_frac_N10_adder_chain_40nm_openfpga.xml
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/auto_sim_openfpga.xml
openfpga_vpr_device_layout=2x2
openfpga_sim_setting_file=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_simulation_settings/fixed_sim_openfpga.xml
openfpga_pin_constraints_file=${PATH:TASK_DIR}/config/dummy_pin_constraints.xml
[ARCHITECTURES]
arch0=${PATH:OPENFPGA_PATH}/openfpga_flow/vpr_arch/k6_frac_N10_tileable_adder_chain_40nm.xml
[BENCHMARKS]
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.blif
bench0=${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/adder/adder_8/adder_8.v
[SYNTHESIS_PARAM]
bench0_top = and2
bench0_act = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.act
bench0_verilog = ${PATH:OPENFPGA_PATH}/openfpga_flow/benchmarks/micro_benchmark/and2/and2.v
bench0_chan_width = 300
# Yosys script parameters
bench_yosys_cell_sim_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_adders_sim.v
bench_yosys_adder_map_verilog_common=${PATH:OPENFPGA_PATH}/openfpga_flow/openfpga_yosys_techlib/openfpga_arith_map.v
bench_read_verilog_options_common = -nolatches
bench_yosys_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_adder_flow.ys
bench_yosys_rewrite_common=${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_yosys_vpr_flow_with_rewrite.ys;${PATH:OPENFPGA_PATH}/openfpga_flow/misc/ys_tmpl_rewrite_flow.ys
# Benchmark information
bench0_top = adder_8
[SCRIPT_PARAM_MIN_ROUTE_CHAN_WIDTH]
end_flow_with_test=