The netlists that appear in bin/scd/netlists/ after a build are synthesized
from Verilog that is checked into this directory, one subdirectory per function.
The netlist file names carry their parameters, so mult_64bit_64cc is
mult/mult.v at 64 bits over 64 clock cycles:
| Shipped netlist | Source |
|---|---|
sum_8bit_1cc, sum_nbit_ncc |
sum/sum.v |
mult_*bit_*cc |
mult/mult.v |
hamming_*bit_*cc |
hamming/hamming.v |
compare_nbit_ncc |
compare/compare.v |
encoder_32bit_1cc |
encoder/encoder.v |
aes_1cc, aes_11cc |
aes/ |
sha3_24cc |
sha3/ |
cordic_32bit_31cc |
cordic/ |
matrix_mult_nxn_32bit_n3cc |
matrix_mult/ |
k_nns_31bit_4nei_ncc |
knns/ |
knns_td_32bit_4nei_ncc |
knns_td/ |
rsa_1024bit_2097152cc |
rsa/ |
mips_32bit_64mem_ncc |
mips/ |
a23_gc_main_*_w_n_cc |
a23/ |
public_test_8bit_ncc |
public_test/public_test.v |
non_secret_test_8bit_ncc |
non_secret_test/non_secret_test.v |
The one exception is mux_8bit_1cc, which is a hand-written netlist (it
instantiates MUX cells directly) and so has no higher-level source.
Several functions have source here but no pre-built netlist, and need
synthesizing before use: div, float, argmax,
select, stable_match,
stack_machine.
The shared building blocks the benchmarks instantiate (ADD, MULT, COMP,
DIV, MUX, shifters, ...) live in syn_lib/ and must be read in
before the benchmark itself.
For a walkthrough of all four stages on one function, from sum.v to two
parties running the protocol, see the
complete workflow example.
Netlist generation requires Synopsys Design Compiler or Yosys-ABC synthesis tools.
[This part is mentioned only for documentation and it is already done, please skip.]
Go to circuit_synthesis/lib/dff_full and compile the library:
$ cd circuit_synthesis/lib/dff_full
$ ./compile
Advanced detailed: Let's suppose that our_lib.lib is located in /path/to/our_lib.
- Go inside /path/to/our_lib and run:
$ lc_shell
lc_shell> set search_path [concat /path/to/our_lib/]
lc_shell> read_lib our_lib.lib
lc_shell> write_lib our_lib -format db
lc_shell> exit
[Note: commands starting with "lc_shell>" should be called inside lc_shell.
Please ignore "lc_shell>" for them].
Go inside circuit_synthesis/benchmark, where benchmark is the name of the function
and compile the benchmark to generate the netlist:
$ cd benchmark
$ ./compile
You can edit benchmark.dcsh file to change synthesis parameters.
Advanced detailed: Let's suppose that our_lib.db is compiled and located
in /path/to/our_lib and benchmark.v is located in /path/to/benchmark/.
- Go to
/path/to/benchmark/and run:
$ design_vision
design_vision> elaborate benchmark -architecture verilog -library DEFAULT -update
design_vision> set_max_area -ignore_tns 0
design_vision> set_flatten false -design *
design_vision> set_structure -design * false
design_vision> set_resource_allocation area_only
design_vision> report_compile_options
design_vision> compile -ungroup_all -boundary_optimization -map_effort high -area_effort high -no_design_rule
design_vision> write -hierarchy -format verilog -output benchmark_syn.v
design_vision> exit
It creates benchmark_syn.v in the current directory. [Note: commands
starting with "design_vision>" should be called inside design_vision.
Please ignore "design_vision>" for them.]
You can use script/count.sh to count the number of gates in
the generated netlist file. For counting gates in
/path/to/benchmark/benchmark_syn.v, simply run:
$ script/count.sh /path/to/benchmark/benchmark_syn.v
Yosys is a free alternative to Design Compiler and is enough to take a
benchmark all the way to a .scd file. This flow is verified end to end with
Yosys 0.33 and Yosys 0.68: synthesis, V2SCD_Main translation, and a
functional check of the result with SCD_Evaluator_Main.
Working Yosys scripts live next to the benchmarks they synthesize:
sum/sum.yos and knns_td/knns_td.yos.
Run one from inside its own directory, since the paths in it are relative, and
note that a script file is passed with -s:
$ cd sum
$ yosys -s sum.yos
That writes the netlist to sum_syn_yos.v. Translate it and check it:
$ bin/scd/V2SCD_Main -i circuit_synthesis/sum/sum_syn_yos.v -o sum.scd
$ bin/scd/SCD_Evaluator_Main -i sum.scd --g_input 05 --e_input 03
08
Copy sum.yos and adapt it. For a function in benchmark.v with top module
benchmark:
read_verilog ../syn_lib/*.v
read_verilog benchmark.v
hierarchy -check -top benchmark
proc; fsm; flatten; opt;
techmap; opt;
dfflibmap -liberty ../lib/asic_cell_yosys_extended.lib
abc -liberty ../lib/asic_cell_yosys_extended.lib -script ../lib/script.abc;
opt; clean;
opt_clean -purge
stat -liberty ../lib/asic_cell_yosys_extended.lib
write_verilog -noattr -noexpr benchmark_syn.v
Each step that is not obvious is there for a reason:
dfflibmapis required.abcmaps combinational logic only and leaves flip-flops as Yosys internal cells, so without this step the DFFs never get theI(initial value) pin thatV2SCD_Mainneeds, and you get an error about a missingI.-noattr -noexpronwrite_verilogis required. The netlist parser does not understand Verilog attributes or expression syntax. Comments are fine.- The cell library needs a
BUFcell. Yosys 0.68 warnsgenlib library reader cannot detect the buffer gatewithout one, and newer ABC versions can refuse to map at all. Both libraries inlib/now have one. ABUFin the resulting netlist is free — it becomes a wire alias, not a gate. ../syn_libmust be read before the benchmark, since it holds the hand-written building blocks (ADD,MULT,COMP, ...) that the benchmarks instantiate.
To override a benchmark's parameters, pass them to hierarchy. The sequential
8-bit / 8-cycle version of sum, which adds one bit per clock cycle, is:
hierarchy -check -top sum -chparam N 8 -chparam CC 8
Its netlist is checked in as
scd/netlists/test/sum_yosys_1bit_8cc.v
and is covered by the test suite, so it doubles as a reference for what a
current Yosys emits.
Always cross-check a freshly synthesized circuit in the clear before running the GC protocol, since a mis-synthesized circuit and a protocol bug look alike:
$ bin/scd/SCD_Evaluator_Main -i sum_seq.scd -c 8 --g_input 6D --e_input 39
A6
Sequential circuits need -c <clock_cycles>; without it only the first cycle is
evaluated and the answer looks wrong rather than failing outright.
div/div.v instantiates Synopsys' DesignWare DW_div macro, which is not part
of this repository and is only available inside Design Compiler with a
DesignWare license. Yosys therefore cannot synthesize it and fails with:
ERROR: Module `\DW_div' referenced in module `\div' in cell `\U1' is not part of the design.
div/div_unsigned.v is a synthesizable replacement, built
on the restoring divider in syn_lib/DIV.v and usable with
either Yosys or Design Compiler.
Mind the signedness. DIV.v is unsigned. syn_lib/DIV_.v is the signed
(two's complement) variant, and wrapping it looks exactly like
div_unsigned.v with DIV_ in place of DIV. The same bit pattern means
different numbers to the two: with N=8, 0x82 is 130 unsigned but -126
signed, so 0x82 / 0x05 is 0x1A (26) unsigned and 0xE7 (-25) signed.
Neither is wrong, but a signed divider fed unsigned data is the usual
explanation for a divider that "works for small numbers" and then fails once an
operand's top bit is set.
Division by zero is not defined for either.
$ cd div
$ yosys -s div_unsigned.yos
$ bin/scd/V2SCD_Main -i div_unsigned_syn_yos.v -o div.scd
$ bin/scd/SCD_Evaluator_Main -i div.scd --g_input 82 --e_input 05
1A
The ports must be named g_input, e_input and o and must be
one-dimensional, because a .scd file is a flat vector of wires. A synthesized
2-D port bit such as g_input[1][3] is rejected by the parser.
The restriction applies to the ports, not to the logic.
multidim/multidim.v shows the pattern: keep the ports
flat, unpack them into 2-D arrays with a generate block, and write the logic
against the arrays. Synthesis flattens the unpacking away, so it costs no gates.
The example computes the elementwise sum of two ROWS x COLS grids of
WIDTH-bit values.