Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
sudo apt-get install -y git build-essential pkg-config cmake ccache gperf bison flex \
libreadline-dev gawk tcl-dev libffi-dev graphviz xdot python3 \
libboost-system-dev libboost-python-dev libboost-filesystem-dev \
zlib1g-dev libfl-dev
zlib1g-dev libfl-dev libsodium-dev nlohmann-json3-dev

- uses: actions/checkout@v4
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
.o
build/
netlist_synth_fpga.verilog
tiny_area_lut4.blif
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,14 @@ The configuration format is still work in progress. A draft format specification
"<str, name of define>": <str or int, value of define>
}
"pack_command": "DSP packing command" (optional)
},
"adders": { (optional)
"techmap": <path, relative path to yosys hard carry-chain adder tech mapping file>
}
}
```

Sections version, partname, lut_size, flip-flops, are required. Sections root_path, brams,and dsps are optional. If "root_path" is not specified, it will correspond to the path where the config file is located.
Sections version, partname, lut_size, flip-flops, are required. Sections root_path, brams, dsps, and adders are optional. If "root_path" is not specified, it will correspond to the path where the config file is located. The "adders" techmap (applied after `alumacc` and before the generic techmap, independently of DSP inference) maps `$alu` onto a hard carry-chain adder primitive; when absent, adders remain in soft logic.

### Logic Only Example: No BRAMs or DSPs

Expand Down
77 changes: 77 additions & 0 deletions src/synth_fpga.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ struct SynthFpgaPass : public ScriptPass {
dict<string, string> ys_dsps_parameter_string;
string ys_dsps_pack_command = "";

// Adders (carry chain)
//
string ys_adders_techmap = "";

// Methods
//
SynthFpgaPass() : ScriptPass("synth_fpga", "Zero Asic FPGA synthesis flow") {}
Expand Down Expand Up @@ -416,6 +420,11 @@ struct SynthFpgaPass : public ScriptPass {
dict<string, string> dsps_parameter_string;
string dsps_pack_command;

//
// Adder (carry chain) related
//
string adders_techmap;

} config_type;

// The global config object
Expand Down Expand Up @@ -499,6 +508,9 @@ struct SynthFpgaPass : public ScriptPass {
log(" DSP pack_command : \n");
log(" %s\n", (G_config.dsps_pack_command).c_str());

log(" ADDER techmap : \n");
log(" %s\n", (G_config.adders_techmap).c_str());

log(" ====================================================================="
"=====\n");
}
Expand Down Expand Up @@ -596,6 +608,18 @@ struct SynthFpgaPass : public ScriptPass {
ys_dsps_pack_command = G_config.dsps_pack_command;
}

// Adder (carry chain) techmap setting. Resolved relative to root_path
// just like the DSP/BRAM/DFF techmaps.
//
if (G_config.adders_techmap == "") {

ys_adders_techmap = "";

} else {

ys_adders_techmap = G_config.root_path + "/" + G_config.adders_techmap;
}

// We call the 'dsp_tech' through the config file mechanism as 'config'
// (why not ? ;-)
//
Expand Down Expand Up @@ -1254,6 +1278,30 @@ struct SynthFpgaPass : public ScriptPass {
G_config.dsps_pack_command = dsps_pack_command->data_string;
}

// adders (optional carry-chain hard adder techmap)
//
JsonNode *adders = NULL;
if (root.data_dict.count("adders") != 0) {
adders = root.data_dict.at("adders");
if (adders->type != 'D') {
log_error("'adders' must be a dictionnary.\n");
}
}

// Adder techmap file (optional : absence leaves adders in soft logic).
//
if (!adders || (adders->data_dict.count("techmap") == 0)) {
G_config.adders_techmap = "";

} else {

JsonNode *adders_techmap = adders->data_dict.at("techmap");
if (adders_techmap->type != 'S') {
log_error("'techmap' associated to 'adders' must be a string.\n");
}
G_config.adders_techmap = adders_techmap->data_string;
}

log_header(yosys_get_design(),
"Reading config file '%s' done with success !\n",
config_file.c_str());
Expand Down Expand Up @@ -2899,6 +2947,29 @@ struct SynthFpgaPass : public ScriptPass {
}
}

// -------------------------
// infer_adders
// -------------------------
//
// Map arithmetic ($alu, produced by 'alumacc') onto the target hard
// carry-chain 'adder' primitive using the config-provided techmap file.
// Deliberately independent of DSP inference (not gated by 'no_dsp'), and must
// be called AFTER 'alumacc' (which creates the $alu cells) and BEFORE the
// generic 'techmap -map +/techmap.v' (which would otherwise lower $alu to
// soft gates). A no-op when no adder techmap is configured.
//
void infer_adders() {
if (ys_adders_techmap == "") {
return;
}

run("stat");

run("techmap -map " + ys_adders_techmap);

run("stat");
}

// -------------------------
// resynthesize
// -------------------------
Expand Down Expand Up @@ -3604,6 +3675,12 @@ struct SynthFpgaPass : public ScriptPass {
//
run("pmux2shiftx");

// Map $alu onto the target hard carry-chain 'adder' primitive (if a config
// adder techmap is provided) before the generic techmap lowers it to soft
// gates. No-op otherwise.
//
infer_adders();

run("techmap -map +/techmap.v");

// BRAM inference
Expand Down
17 changes: 17 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,23 @@ set(ALL_TESTS
unit/dsp/mae-techmap-efpga_mult_addc_regi_unsigned.ys
unit/dsp/mae-techmap-efpga_mult_addc_rego_unsigned.ys
unit/dsp/mae-techmap-efpga_mult_addc_regio_unsigned.ys
unit/carrychain/carrychain-techmap-add_unsigned.ys
unit/carrychain/carrychain-techmap-add_signed.ys
unit/carrychain/carrychain-techmap-add_carry_in.ys
unit/carrychain/carrychain-techmap-sub.ys
unit/carrychain/carrychain-techmap-increment.ys
unit/carrychain/carrychain-techmap-compare.ys
unit/carrychain/carrychain-techmap-accumulator.ys
unit/carrychain/carrychain-techmap-wide_add.ys
unit/carrychain/carrychain-techmap-two_adders.ys
unit/carrychain/carrychain-techmap-undeclared_primitive.ys
unit/carrychain/carrychain-techmap-with_dsp.ys
unit/carrychain/carrychain-techmap-with_no_dsp.ys
unit/carrychain/carrychain-techmap-abspath.ys
unit/carrychain/carrychain-techmap-min8_wide.ys
unit/carrychain/carrychain-techmap-min8_narrow.ys
unit/carrychain/carrychain-no_techmap-soft_logic.ys
unit/carrychain/carrychain-show_config.ys
unit/dsp/mae-techmap-efpga_adder_unsigned.ys
unit/dsp/mae-techmap-efpga_adder_regi_unsigned.ys
unit/dsp/mae-techmap-efpga_adder_rego_unsigned.ys
Expand Down
29 changes: 29 additions & 0 deletions tests/unit/carrychain/carrychain-no_techmap-soft_logic.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# yosys -m wildebeest -s carrychain-no_techmap-soft_logic.ys

#Negative control : the very same adder, synthesized with a config that has
#no 'adders' section, stays in soft logic. That config differs from
#'carrychain.json' by that section only.

read_verilog -lib ../data/carrychain/models/tech_carry.v

read_verilog <<EOF
module carrychain_no_techmap
# (
parameter WIDTH = 8
)
(
input [(WIDTH-1):0] a,
input [(WIDTH-1):0] b,
output [WIDTH:0] y
);

assign y = a + b;

endmodule
EOF

synth_fpga -config ../data/carrychain/carrychain_no_adders.json

select -assert-count 0 */t:efpga_carry
select -assert-count 0 */t:$alu
select -assert-min 1 */t:$lut
29 changes: 29 additions & 0 deletions tests/unit/carrychain/carrychain-show_config.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# yosys -m wildebeest -s carrychain-show_config.ys

#'-show_config' must report the configured adder techmap, and that same file
#must then really be handed over to the 'techmap' pass.

logger -expect log ".*ADDER techmap.*" 1
logger -expect log ".*Verilog-2005 frontend: .*data/carrychain/tech_adder.v.*" 1

read_verilog -lib ../data/carrychain/models/tech_carry.v

read_verilog <<EOF
module carrychain_show_config
# (
parameter WIDTH = 8
)
(
input [(WIDTH-1):0] a,
input [(WIDTH-1):0] b,
output [WIDTH:0] y
);

assign y = a + b;

endmodule
EOF

synth_fpga -config ../data/carrychain/carrychain.json -show_config

select -assert-count 9 */t:efpga_carry
31 changes: 31 additions & 0 deletions tests/unit/carrychain/carrychain-techmap-abspath.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# yosys -m wildebeest -s carrychain-techmap-abspath.ys

#The adder techmap path is resolved against 'root_path' like every other
#techmap path : the leading '/' form must resolve the same way (same idea as
#'heartbeat-z1010-config-abspath.ys').

read_verilog -lib ../data/carrychain/models/tech_carry.v

read_verilog <<EOF
module carrychain_abspath
# (
parameter WIDTH = 8
)
(
input [(WIDTH-1):0] a,
input [(WIDTH-1):0] b,
output [WIDTH:0] y
);

assign y = a + b;

endmodule
EOF

synth_fpga -config ../data/carrychain/carrychain_abspath.json

#The whole adder is in the carry chain : no '$alu' survived and no soft
#logic was needed.
select -assert-count 9 */t:efpga_carry
select -assert-count 0 */t:$alu
select -assert-count 0 */t:$lut
40 changes: 40 additions & 0 deletions tests/unit/carrychain/carrychain-techmap-accumulator.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# yosys -m wildebeest -s carrychain-techmap-accumulator.ys

#A registered accumulator : the adder goes to the hard carry chain while the
#state still legalizes onto the flip flops described by the config.

read_verilog -lib ../data/carrychain/models/tech_carry.v

read_verilog <<EOF
module carrychain_accumulator
# (
parameter WIDTH = 8
)
(
input clk,
input resetn,
input [(WIDTH-1):0] a,
output reg [(WIDTH-1):0] y
);

always @(posedge clk or negedge resetn) begin
if (~resetn) begin
y <= 'h0;
end
else begin
y <= y + a;
end
end

endmodule
EOF

synth_fpga -config ../data/carrychain/carrychain.json

#The whole adder is in the carry chain : no '$alu' survived and no soft
#logic was needed.
select -assert-count 8 */t:efpga_carry
select -assert-count 0 */t:$alu
select -assert-count 0 */t:$lut

select -assert-count 8 */t:dffr
34 changes: 34 additions & 0 deletions tests/unit/carrychain/carrychain-techmap-add_carry_in.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# yosys -m wildebeest -s carrychain-techmap-add_carry_in.ys

#'a + b + ci' folds the extra term into the 'CI' port of the '$alu', so the
#'ci' primary input must reach exactly one carry cell : the bottom of the
#chain.

read_verilog -lib ../data/carrychain/models/tech_carry.v

read_verilog <<EOF
module carrychain_add_carry_in
# (
parameter WIDTH = 8
)
(
input [(WIDTH-1):0] a,
input [(WIDTH-1):0] b,
input ci,
output [WIDTH:0] y
);

assign y = a + b + ci;

endmodule
EOF

synth_fpga -config ../data/carrychain/carrychain.json

#The whole adder is in the carry chain : no '$alu' survived and no soft
#logic was needed.
select -assert-count 9 */t:efpga_carry
select -assert-count 0 */t:$alu
select -assert-count 0 */t:$lut

select -assert-count 1 */w:ci %co */t:efpga_carry %i
30 changes: 30 additions & 0 deletions tests/unit/carrychain/carrychain-techmap-add_signed.ys
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# yosys -m wildebeest -s carrychain-techmap-add_signed.ys

#A signed adder maps onto the hard carry chain just like the unsigned one :
#the sign extension is absorbed by the '$pos' conversions of the techmap.

read_verilog -lib ../data/carrychain/models/tech_carry.v

read_verilog <<EOF
module carrychain_add_signed
# (
parameter WIDTH = 8
)
(
input signed [(WIDTH-1):0] a,
input signed [(WIDTH-1):0] b,
output signed [WIDTH:0] y
);

assign y = a + b;

endmodule
EOF

synth_fpga -config ../data/carrychain/carrychain.json

#The whole adder is in the carry chain : no '$alu' survived and no soft
#logic was needed.
select -assert-count 9 */t:efpga_carry
select -assert-count 0 */t:$alu
select -assert-count 0 */t:$lut
Loading
Loading