From bd26e070d05a2851e2a244d98b9ca3a74ae186a6 Mon Sep 17 00:00:00 2001 From: petergrossmann21 Date: Wed, 5 Aug 2026 13:36:00 -0400 Subject: [PATCH 1/4] Add adder techmap pass --- src/synth_fpga.cc | 77 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/synth_fpga.cc b/src/synth_fpga.cc index c05bf86..7fbb3a2 100644 --- a/src/synth_fpga.cc +++ b/src/synth_fpga.cc @@ -98,6 +98,10 @@ struct SynthFpgaPass : public ScriptPass { dict 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") {} @@ -415,6 +419,11 @@ struct SynthFpgaPass : public ScriptPass { dict dsps_parameter_string; string dsps_pack_command; + // + // Adder (carry chain) related + // + string adders_techmap; + } config_type; // The global config object @@ -498,6 +507,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"); } @@ -595,6 +607,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 ? ;-) // @@ -1253,6 +1277,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()); @@ -2865,6 +2913,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 // ------------------------- @@ -3538,6 +3609,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 From 01766a99cb69fea1f4c1cddf37d63126fa95ca11 Mon Sep 17 00:00:00 2001 From: petergrossmann21 Date: Wed, 5 Aug 2026 13:36:11 -0400 Subject: [PATCH 2/4] Update docs to describe adder techmapping --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2cfd16d..8cee917 100644 --- a/README.md +++ b/README.md @@ -221,11 +221,14 @@ The configuration format is still work in progress. A draft format specification "": } "pack_command": "DSP packing command" (optional) + }, + "adders": { (optional) + "techmap": } } ``` -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 From 3200a30a338b2d8ade4b00ea9c0a2e05ec2d9ea4 Mon Sep 17 00:00:00 2001 From: Thierry Besson Date: Tue, 11 Aug 2026 15:19:20 -0400 Subject: [PATCH 3/4] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dd066bd..3f85cf8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -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: From 5c634ac468f59499616f02626f8192e9be83bc1a Mon Sep 17 00:00:00 2001 From: petergrossmann21 Date: Fri, 21 Aug 2026 10:39:29 -0400 Subject: [PATCH 4/4] Add unit tests --- .gitignore | 1 + tests/CMakeLists.txt | 17 +++++ .../carrychain-no_techmap-soft_logic.ys | 29 ++++++++ .../unit/carrychain/carrychain-show_config.ys | 29 ++++++++ .../carrychain/carrychain-techmap-abspath.ys | 31 +++++++++ .../carrychain-techmap-accumulator.ys | 40 +++++++++++ .../carrychain-techmap-add_carry_in.ys | 34 +++++++++ .../carrychain-techmap-add_signed.ys | 30 ++++++++ .../carrychain-techmap-add_unsigned.ys | 36 ++++++++++ .../carrychain/carrychain-techmap-compare.ys | 28 ++++++++ .../carrychain-techmap-increment.ys | 29 ++++++++ .../carrychain-techmap-min8_narrow.ys | 26 +++++++ .../carrychain-techmap-min8_wide.ys | 30 ++++++++ .../unit/carrychain/carrychain-techmap-sub.ys | 29 ++++++++ .../carrychain-techmap-two_adders.ys | 37 ++++++++++ ...carrychain-techmap-undeclared_primitive.ys | 31 +++++++++ .../carrychain/carrychain-techmap-wide_add.ys | 30 ++++++++ .../carrychain/carrychain-techmap-with_dsp.ys | 33 +++++++++ .../carrychain-techmap-with_no_dsp.ys | 35 ++++++++++ tests/unit/data/carrychain/carrychain.json | 23 +++++++ .../data/carrychain/carrychain_abspath.json | 23 +++++++ .../unit/data/carrychain/carrychain_dsp.json | 44 ++++++++++++ .../unit/data/carrychain/carrychain_min8.json | 23 +++++++ .../data/carrychain/carrychain_no_adders.json | 20 ++++++ .../unit/data/carrychain/models/tech_carry.v | 21 ++++++ tests/unit/data/carrychain/tech_adder.v | 65 +++++++++++++++++ tests/unit/data/carrychain/tech_adder_min8.v | 69 +++++++++++++++++++ 27 files changed, 843 insertions(+) create mode 100644 tests/unit/carrychain/carrychain-no_techmap-soft_logic.ys create mode 100644 tests/unit/carrychain/carrychain-show_config.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-abspath.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-accumulator.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-add_carry_in.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-add_signed.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-add_unsigned.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-compare.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-increment.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-min8_narrow.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-min8_wide.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-sub.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-two_adders.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-undeclared_primitive.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-wide_add.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-with_dsp.ys create mode 100644 tests/unit/carrychain/carrychain-techmap-with_no_dsp.ys create mode 100644 tests/unit/data/carrychain/carrychain.json create mode 100644 tests/unit/data/carrychain/carrychain_abspath.json create mode 100644 tests/unit/data/carrychain/carrychain_dsp.json create mode 100644 tests/unit/data/carrychain/carrychain_min8.json create mode 100644 tests/unit/data/carrychain/carrychain_no_adders.json create mode 100644 tests/unit/data/carrychain/models/tech_carry.v create mode 100644 tests/unit/data/carrychain/tech_adder.v create mode 100644 tests/unit/data/carrychain/tech_adder_min8.v diff --git a/.gitignore b/.gitignore index 5fbcefb..760071a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .o build/ netlist_synth_fpga.verilog +tiny_area_lut4.blif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6488c8a..09b0a6d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -31,6 +31,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 ) foreach(test_script ${ALL_TESTS}) diff --git a/tests/unit/carrychain/carrychain-no_techmap-soft_logic.ys b/tests/unit/carrychain/carrychain-no_techmap-soft_logic.ys new file mode 100644 index 0000000..f532db9 --- /dev/null +++ b/tests/unit/carrychain/carrychain-no_techmap-soft_logic.ys @@ -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 < 9 bit adder must map entirely onto the hard +#carry chain : one 'efpga_carry' per result bit and nothing left in soft +#logic. + +read_verilog -lib ../data/carrychain/models/tech_carry.v + +read_verilog < b); + +endmodule +EOF + +synth_fpga -config ../data/carrychain/carrychain.json + +select -assert-count 8 */t:efpga_carry +select -assert-count 0 */t:$alu diff --git a/tests/unit/carrychain/carrychain-techmap-increment.ys b/tests/unit/carrychain/carrychain-techmap-increment.ys new file mode 100644 index 0000000..ce3c7a2 --- /dev/null +++ b/tests/unit/carrychain/carrychain-techmap-increment.ys @@ -0,0 +1,29 @@ +# yosys -m wildebeest -s carrychain-techmap-increment.ys + +#An incrementer is an '$alu' with a constant operand : it must be mapped onto +#the hard carry chain rather than onto soft logic. + +read_verilog -lib ../data/carrychain/models/tech_carry.v + +read_verilog <