summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuben Undheim <ruben.undheim@gmail.com>2018-08-30 20:46:20 +0200
committerRuben Undheim <ruben.undheim@gmail.com>2018-08-30 20:46:20 +0200
commit5033b51947a6ef02cb785b5622e993335efa750a (patch)
tree7bed18c526bd94917fa2f08e3df12209863698a1
parentfefe0fc0430f4f173a25e674708aa0f4f0854b31 (diff)
New upstream version 0.7+20180830git0b7a184
-rw-r--r--.github/issue_template.md16
-rw-r--r--.gitignore8
-rw-r--r--.travis.yml176
-rwxr-xr-x.travis/build-and-test.sh49
-rw-r--r--.travis/common.sh15
-rwxr-xr-x.travis/deploy-after-success.sh6
-rwxr-xr-x.travis/setup.sh97
-rw-r--r--Brewfile8
-rw-r--r--CHANGELOG13
-rw-r--r--COPYING13
-rw-r--r--CodingReadme98
-rw-r--r--Makefile313
-rw-r--r--README.md (renamed from README)240
-rw-r--r--backends/aiger/Makefile.inc3
-rw-r--r--backends/aiger/aiger.cc754
-rw-r--r--backends/blif/blif.cc82
-rw-r--r--backends/btor/README23
-rw-r--r--backends/btor/btor.cc1876
-rw-r--r--backends/btor/test_cells.sh30
-rwxr-xr-xbackends/btor/verilog2btor.sh37
-rw-r--r--backends/edif/edif.cc181
-rw-r--r--backends/edif/runtest.py121
-rw-r--r--backends/firrtl/.gitignore2
-rw-r--r--backends/firrtl/Makefile.inc3
-rw-r--r--backends/firrtl/firrtl.cc677
-rw-r--r--backends/firrtl/test.sh25
-rw-r--r--backends/firrtl/test.v63
-rw-r--r--backends/ilang/ilang_backend.cc10
-rw-r--r--backends/intersynth/intersynth.cc4
-rw-r--r--backends/json/json.cc18
-rw-r--r--backends/protobuf/.gitignore2
-rw-r--r--backends/protobuf/Makefile.inc8
-rw-r--r--backends/protobuf/protobuf.cc370
-rw-r--r--backends/simplec/.gitignore2
-rw-r--r--backends/simplec/Makefile.inc3
-rw-r--r--backends/simplec/simplec.cc810
-rw-r--r--backends/simplec/test00.sh5
-rw-r--r--backends/simplec/test00_tb.c93
-rw-r--r--backends/simplec/test00_uut.v14
-rw-r--r--backends/smt2/Makefile.inc2
-rw-r--r--backends/smt2/smt2.cc728
-rw-r--r--backends/smt2/smtbmc.py944
-rw-r--r--backends/smt2/smtio.py458
-rw-r--r--backends/smv/smv.cc14
-rw-r--r--backends/spice/spice.cc4
-rw-r--r--backends/table/Makefile.inc3
-rw-r--r--backends/table/table.cc120
-rw-r--r--backends/verilog/verilog_backend.cc223
-rw-r--r--examples/aiger/.gitignore5
-rw-r--r--examples/aiger/README22
-rw-r--r--examples/aiger/demo.sh14
-rw-r--r--examples/aiger/demo.v12
-rw-r--r--examples/basys3/example.xdc3
-rw-r--r--examples/basys3/run_prog.tcl1
-rw-r--r--examples/cmos/counter.ys10
-rw-r--r--examples/cmos/counter_tb.v4
-rw-r--r--examples/cmos/testbench_digital.sh2
-rw-r--r--examples/cxx-api/evaldemo.cc2
-rw-r--r--examples/gowin/.gitignore8
-rw-r--r--examples/gowin/README17
-rw-r--r--examples/gowin/demo.cst41
-rw-r--r--examples/gowin/demo.sdc1
-rw-r--r--examples/gowin/demo.v12
-rw-r--r--examples/gowin/run.sh12
-rw-r--r--examples/gowin/testbench.v40
-rw-r--r--examples/intel/DE2i-150/quartus_compile/de2i.qpf4
-rw-r--r--examples/intel/DE2i-150/quartus_compile/de2i.qsf1099
-rw-r--r--examples/intel/DE2i-150/quartus_compile/runme_quartus7
-rw-r--r--examples/intel/DE2i-150/run_cycloneiv2
-rw-r--r--examples/intel/DE2i-150/sevenseg.v25
-rw-r--r--examples/intel/DE2i-150/top.v15
-rw-r--r--examples/intel/MAX10/run_max101
-rw-r--r--examples/intel/MAX10/runme_postsynth5
-rw-r--r--examples/intel/MAX10/sevenseg.v25
-rw-r--r--examples/intel/MAX10/top.v15
-rw-r--r--examples/intel/asicworld_lfsr/README6
-rw-r--r--examples/intel/asicworld_lfsr/lfsr_updown.v35
-rw-r--r--examples/intel/asicworld_lfsr/lfsr_updown_tb.v34
-rwxr-xr-xexamples/intel/asicworld_lfsr/run_cycloneiv2
-rwxr-xr-xexamples/intel/asicworld_lfsr/run_max102
-rwxr-xr-xexamples/intel/asicworld_lfsr/runme_postsynth5
-rwxr-xr-xexamples/intel/asicworld_lfsr/runme_presynth5
-rw-r--r--examples/osu035/.gitignore3
-rw-r--r--examples/osu035/Makefile13
-rw-r--r--examples/osu035/example.constr2
-rw-r--r--examples/osu035/example.v3
-rw-r--r--examples/osu035/example.ys11
-rw-r--r--examples/smtbmc/.gitignore2
-rw-r--r--examples/smtbmc/Makefile11
-rw-r--r--examples/smtbmc/demo2.v2
-rw-r--r--examples/smtbmc/demo8.v12
-rw-r--r--frontends/ast/ast.cc94
-rw-r--r--frontends/ast/ast.h33
-rw-r--r--frontends/ast/genrtlil.cc209
-rw-r--r--frontends/ast/simplify.cc482
-rw-r--r--frontends/blif/blifparse.cc159
-rw-r--r--frontends/blif/blifparse.h3
-rw-r--r--frontends/ilang/.gitignore2
-rw-r--r--frontends/ilang/Makefile.inc7
-rw-r--r--frontends/ilang/ilang_frontend.cc4
-rw-r--r--frontends/ilang/ilang_lexer.l2
-rw-r--r--frontends/json/Makefile.inc3
-rw-r--r--frontends/json/jsonparse.cc541
-rw-r--r--frontends/liberty/liberty.cc73
-rw-r--r--frontends/verific/Makefile.inc3
-rw-r--r--frontends/verific/README62
-rw-r--r--frontends/verific/build_amd64.txt30
-rw-r--r--frontends/verific/example.sby16
-rw-r--r--frontends/verific/example.sv18
-rw-r--r--frontends/verific/test_navre.ys18
-rw-r--r--frontends/verific/verific.cc1870
-rw-r--r--frontends/verific/verific.h106
-rw-r--r--frontends/verific/verificsva.cc1814
-rw-r--r--frontends/verilog/.gitignore2
-rw-r--r--frontends/verilog/Makefile.inc7
-rw-r--r--frontends/verilog/const2ast.cc8
-rw-r--r--frontends/verilog/preproc.cc189
-rw-r--r--frontends/verilog/verilog_frontend.cc121
-rw-r--r--frontends/verilog/verilog_frontend.h3
-rw-r--r--frontends/verilog/verilog_lexer.l55
-rw-r--r--frontends/verilog/verilog_parser.y440
-rw-r--r--frontends/vhdl2verilog/Makefile.inc1
-rw-r--r--frontends/vhdl2verilog/vhdl2verilog.cc183
-rw-r--r--kernel/calc.cc4
-rw-r--r--kernel/cellaigs.cc16
-rw-r--r--kernel/celledges.h6
-rw-r--r--kernel/celltypes.h15
-rw-r--r--kernel/consteval.h9
-rw-r--r--kernel/cost.h30
-rw-r--r--kernel/driver.cc175
-rw-r--r--kernel/hashlib.h9
-rw-r--r--kernel/log.cc149
-rw-r--r--kernel/log.h17
-rw-r--r--kernel/modtools.h10
-rw-r--r--kernel/register.cc15
-rw-r--r--kernel/register.h14
-rw-r--r--kernel/rtlil.cc339
-rw-r--r--kernel/rtlil.h342
-rw-r--r--kernel/satgen.h39
-rw-r--r--kernel/yosys.cc97
-rw-r--r--kernel/yosys.h16
-rw-r--r--libs/ezsat/ezminisat.cc6
-rw-r--r--libs/minisat/00_PATCH_no_fpu_control.patch43
-rw-r--r--libs/minisat/00_PATCH_remove_zlib.patch17
-rw-r--r--libs/minisat/00_PATCH_typofixes.patch20
-rwxr-xr-x[-rw-r--r--]libs/minisat/00_UPDATE.sh6
-rw-r--r--libs/minisat/Dimacs.h8
-rw-r--r--libs/minisat/Options.cc4
-rw-r--r--libs/minisat/SimpSolver.cc4
-rw-r--r--libs/minisat/Solver.cc4
-rw-r--r--libs/minisat/System.cc15
-rw-r--r--libs/minisat/System.h7
-rw-r--r--libs/subcircuit/subcircuit.h2
-rw-r--r--manual/CHAPTER_CellLib.tex6
-rw-r--r--manual/CHAPTER_Prog/stubnets.cc2
-rw-r--r--manual/PRESENTATION_Prog/my_cmd.cc6
-rwxr-xr-xmanual/clean.sh2
-rw-r--r--misc/yosys.proto175
-rw-r--r--passes/cmds/Makefile.inc4
-rw-r--r--passes/cmds/add.cc4
-rw-r--r--passes/cmds/blackbox.cc81
-rw-r--r--passes/cmds/check.cc89
-rw-r--r--passes/cmds/chformal.cc282
-rw-r--r--passes/cmds/chtype.cc83
-rw-r--r--passes/cmds/connect.cc4
-rw-r--r--passes/cmds/connwrappers.cc6
-rw-r--r--passes/cmds/copy.cc4
-rw-r--r--passes/cmds/cover.cc6
-rw-r--r--passes/cmds/delete.cc4
-rw-r--r--passes/cmds/design.cc142
-rw-r--r--passes/cmds/edgetypes.cc4
-rw-r--r--passes/cmds/logcmd.cc4
-rw-r--r--passes/cmds/ltp.cc185
-rw-r--r--passes/cmds/plugin.cc4
-rw-r--r--passes/cmds/qwp.cc5
-rw-r--r--passes/cmds/rename.cc4
-rw-r--r--passes/cmds/scatter.cc4
-rw-r--r--passes/cmds/scc.cc78
-rw-r--r--passes/cmds/select.cc59
-rw-r--r--passes/cmds/setattr.cc12
-rw-r--r--passes/cmds/setundef.cc263
-rw-r--r--passes/cmds/show.cc36
-rw-r--r--passes/cmds/splice.cc4
-rw-r--r--passes/cmds/splitnets.cc14
-rw-r--r--passes/cmds/stat.cc15
-rw-r--r--passes/cmds/tee.cc5
-rw-r--r--passes/cmds/torder.cc4
-rw-r--r--passes/cmds/trace.cc17
-rw-r--r--passes/cmds/write_file.cc5
-rw-r--r--passes/equiv/equiv_add.cc4
-rw-r--r--passes/equiv/equiv_induct.cc4
-rw-r--r--passes/equiv/equiv_make.cc8
-rw-r--r--passes/equiv/equiv_mark.cc4
-rw-r--r--passes/equiv/equiv_miter.cc4
-rw-r--r--passes/equiv/equiv_purge.cc8
-rw-r--r--passes/equiv/equiv_remove.cc4
-rw-r--r--passes/equiv/equiv_simple.cc59
-rw-r--r--passes/equiv/equiv_status.cc4
-rw-r--r--passes/equiv/equiv_struct.cc4
-rw-r--r--passes/fsm/fsm.cc4
-rw-r--r--passes/fsm/fsm_detect.cc8
-rw-r--r--passes/fsm/fsm_expand.cc34
-rw-r--r--passes/fsm/fsm_export.cc4
-rw-r--r--passes/fsm/fsm_extract.cc4
-rw-r--r--passes/fsm/fsm_info.cc4
-rw-r--r--passes/fsm/fsm_map.cc7
-rw-r--r--passes/fsm/fsm_opt.cc4
-rw-r--r--passes/fsm/fsm_recode.cc4
-rw-r--r--passes/hierarchy/Makefile.inc2
-rw-r--r--passes/hierarchy/hierarchy.cc164
-rw-r--r--passes/hierarchy/submod.cc5
-rw-r--r--passes/hierarchy/uniquify.cc (renamed from passes/hierarchy/singleton.cc)43
-rw-r--r--passes/memory/Makefile.inc1
-rw-r--r--passes/memory/memory.cc4
-rw-r--r--passes/memory/memory_bram.cc4
-rw-r--r--passes/memory/memory_collect.cc4
-rw-r--r--passes/memory/memory_dff.cc24
-rw-r--r--passes/memory/memory_map.cc4
-rw-r--r--passes/memory/memory_memx.cc4
-rw-r--r--passes/memory/memory_nordff.cc121
-rw-r--r--passes/memory/memory_share.cc4
-rw-r--r--passes/memory/memory_unpack.cc4
-rw-r--r--passes/opt/Makefile.inc2
-rw-r--r--passes/opt/opt.cc4
-rw-r--r--passes/opt/opt_clean.cc107
-rw-r--r--passes/opt/opt_demorgan.cc202
-rw-r--r--passes/opt/opt_expr.cc315
-rw-r--r--passes/opt/opt_merge.cc19
-rw-r--r--passes/opt/opt_muxtree.cc4
-rw-r--r--passes/opt/opt_reduce.cc4
-rw-r--r--passes/opt/opt_rmdff.cc246
-rw-r--r--passes/opt/rmports.cc187
-rw-r--r--passes/opt/share.cc4
-rw-r--r--passes/opt/wreduce.cc4
-rw-r--r--passes/proc/proc.cc4
-rw-r--r--passes/proc/proc_arst.cc4
-rw-r--r--passes/proc/proc_clean.cc4
-rw-r--r--passes/proc/proc_dff.cc9
-rw-r--r--passes/proc/proc_dlatch.cc20
-rw-r--r--passes/proc/proc_init.cc4
-rw-r--r--passes/proc/proc_mux.cc4
-rw-r--r--passes/proc/proc_rmdead.cc4
-rw-r--r--passes/sat/Makefile.inc2
-rw-r--r--passes/sat/assertpmux.cc4
-rw-r--r--passes/sat/async2sync.cc147
-rw-r--r--passes/sat/clk2fflogic.cc114
-rw-r--r--passes/sat/eval.cc4
-rw-r--r--passes/sat/expose.cc55
-rw-r--r--passes/sat/freduce.cc7
-rw-r--r--passes/sat/miter.cc4
-rw-r--r--passes/sat/sat.cc5
-rw-r--r--passes/sat/sim.cc862
-rw-r--r--passes/techmap/Makefile.inc5
-rw-r--r--passes/techmap/abc.cc612
-rw-r--r--passes/techmap/aigmap.cc4
-rw-r--r--passes/techmap/alumacc.cc19
-rw-r--r--passes/techmap/attrmap.cc12
-rw-r--r--passes/techmap/attrmvcp.cc4
-rw-r--r--passes/techmap/deminout.cc36
-rw-r--r--passes/techmap/dff2dffe.cc18
-rw-r--r--passes/techmap/dff2dffs.cc142
-rw-r--r--passes/techmap/dffinit.cc24
-rw-r--r--passes/techmap/dfflibmap.cc12
-rw-r--r--passes/techmap/dffsr2dff.cc4
-rw-r--r--passes/techmap/extract.cc4
-rw-r--r--passes/techmap/extract_counter.cc (renamed from techlibs/greenpak4/greenpak4_counters.cc)425
-rw-r--r--passes/techmap/extract_fa.cc605
-rw-r--r--passes/techmap/extract_reduce.cc324
-rw-r--r--passes/techmap/hilomap.cc4
-rw-r--r--passes/techmap/insbuf.cc4
-rw-r--r--passes/techmap/iopadmap.cc61
-rw-r--r--passes/techmap/libparse.cc24
-rw-r--r--passes/techmap/lut2mux.cc4
-rw-r--r--passes/techmap/maccmap.cc4
-rw-r--r--passes/techmap/muxcover.cc4
-rw-r--r--passes/techmap/nlutmap.cc6
-rw-r--r--passes/techmap/pmuxtree.cc4
-rw-r--r--passes/techmap/shregmap.cc4
-rw-r--r--passes/techmap/simplemap.cc4
-rw-r--r--passes/techmap/techmap.cc45
-rw-r--r--passes/techmap/tribuf.cc4
-rw-r--r--passes/techmap/zinit.cc4
-rw-r--r--passes/tests/test_abcloop.cc4
-rw-r--r--passes/tests/test_autotb.cc4
-rw-r--r--passes/tests/test_cell.cc6
-rwxr-xr-xtechlibs/achronix/Makefile.inc6
-rwxr-xr-xtechlibs/achronix/speedster22i/cells_arith.v65
-rwxr-xr-xtechlibs/achronix/speedster22i/cells_map.v72
-rwxr-xr-xtechlibs/achronix/speedster22i/cells_sim.v80
-rwxr-xr-xtechlibs/achronix/synth_achronix.cc188
-rw-r--r--techlibs/common/Makefile.inc1
-rw-r--r--techlibs/common/dff2ff.v14
-rw-r--r--techlibs/common/prep.cc32
-rw-r--r--techlibs/common/simcells.v38
-rw-r--r--techlibs/common/simlib.v48
-rw-r--r--techlibs/common/synth.cc21
-rw-r--r--techlibs/coolrunner2/Makefile.inc8
-rw-r--r--techlibs/coolrunner2/cells_latch.v19
-rw-r--r--techlibs/coolrunner2/cells_sim.v310
-rw-r--r--techlibs/coolrunner2/coolrunner2_sop.cc320
-rw-r--r--techlibs/coolrunner2/synth_coolrunner2.cc202
-rw-r--r--techlibs/coolrunner2/tff_extract.v41
-rw-r--r--techlibs/coolrunner2/xc2_dff.lib31
-rw-r--r--techlibs/easic/Makefile.inc3
-rw-r--r--techlibs/easic/synth_easic.cc188
-rw-r--r--techlibs/ecp5/Makefile.inc8
-rw-r--r--techlibs/ecp5/arith_map.v79
-rw-r--r--techlibs/ecp5/cells_map.v135
-rw-r--r--techlibs/ecp5/cells_sim.v448
-rw-r--r--techlibs/ecp5/dram.txt16
-rw-r--r--techlibs/ecp5/drams_map.v28
-rw-r--r--techlibs/ecp5/synth_ecp5.cc331
-rw-r--r--techlibs/gowin/cells_sim.v48
-rw-r--r--techlibs/gowin/synth_gowin.cc10
-rw-r--r--techlibs/greenpak4/Makefile.inc6
-rw-r--r--techlibs/greenpak4/cells_blackbox.v18
-rw-r--r--techlibs/greenpak4/cells_latch.v15
-rw-r--r--techlibs/greenpak4/cells_map.v165
-rw-r--r--techlibs/greenpak4/cells_sim.v462
-rw-r--r--techlibs/greenpak4/cells_sim_ams.v110
-rw-r--r--techlibs/greenpak4/cells_sim_digital.v794
-rw-r--r--techlibs/greenpak4/cells_sim_wip.v136
-rw-r--r--techlibs/greenpak4/greenpak4_dffinv.cc25
-rw-r--r--techlibs/greenpak4/synth_greenpak4.cc15
-rw-r--r--techlibs/ice40/cells_map.v2
-rw-r--r--techlibs/ice40/cells_sim.v436
-rw-r--r--techlibs/ice40/ice40_ffinit.cc4
-rw-r--r--techlibs/ice40/ice40_ffssr.cc4
-rw-r--r--techlibs/ice40/ice40_opt.cc38
-rw-r--r--techlibs/ice40/synth_ice40.cc74
-rw-r--r--techlibs/intel/Makefile.inc24
-rw-r--r--techlibs/intel/a10gx/cells_arith.v65
-rw-r--r--techlibs/intel/a10gx/cells_map.v53
-rw-r--r--techlibs/intel/a10gx/cells_sim.v59
-rw-r--r--techlibs/intel/common/altpll_bb.v366
-rw-r--r--techlibs/intel/common/brams.txt33
-rw-r--r--techlibs/intel/common/brams_map.v93
-rw-r--r--techlibs/intel/common/m9k_bb.v70
-rw-r--r--techlibs/intel/cyclone10/cells_arith.v65
-rw-r--r--techlibs/intel/cyclone10/cells_map.v109
-rw-r--r--techlibs/intel/cyclone10/cells_sim.v137
-rw-r--r--techlibs/intel/cycloneiv/cells_arith.v97
-rw-r--r--techlibs/intel/cycloneiv/cells_map.v93
-rw-r--r--techlibs/intel/cycloneiv/cells_sim.v299
-rw-r--r--techlibs/intel/cycloneive/arith_map.v99
-rw-r--r--techlibs/intel/cycloneive/cells_map.v109
-rw-r--r--techlibs/intel/cycloneive/cells_sim.v292
-rw-r--r--techlibs/intel/cyclonev/cells_arith.v65
-rw-r--r--techlibs/intel/cyclonev/cells_map.v162
-rw-r--r--techlibs/intel/cyclonev/cells_sim.v144
-rw-r--r--techlibs/intel/max10/cells_arith.v65
-rw-r--r--techlibs/intel/max10/cells_map.v93
-rw-r--r--techlibs/intel/max10/cells_sim.v292
-rw-r--r--techlibs/intel/synth_intel.cc270
-rw-r--r--techlibs/xilinx/Makefile.inc2
-rw-r--r--techlibs/xilinx/brams_init.py16
-rw-r--r--techlibs/xilinx/cells_map.v2
-rw-r--r--techlibs/xilinx/cells_sim.v30
-rw-r--r--techlibs/xilinx/drams_bb.v20
-rw-r--r--techlibs/xilinx/lut2lut.v65
-rw-r--r--techlibs/xilinx/synth_xilinx.cc43
-rw-r--r--tests/sat/sizebits.sv32
-rw-r--r--tests/sat/sizebits.ys2
-rw-r--r--tests/simple/arraycells.v2
-rw-r--r--tests/simple/graphtest.v2
-rw-r--r--tests/simple/hierdefparam.v23
-rw-r--r--tests/simple/specify.v31
-rw-r--r--tests/sva/.gitignore7
-rw-r--r--tests/sva/Makefile13
-rw-r--r--tests/sva/basic00.sv12
-rw-r--r--tests/sva/basic01.sv16
-rw-r--r--tests/sva/basic02.sv20
-rw-r--r--tests/sva/basic03.sv12
-rw-r--r--tests/sva/basic04.sv10
-rw-r--r--tests/sva/basic04.vhd26
-rw-r--r--tests/sva/basic05.sv19
-rw-r--r--tests/sva/basic05.vhd26
-rw-r--r--tests/sva/counter.sv30
-rw-r--r--tests/sva/runtest.sh72
-rw-r--r--tests/sva/sva_not.sv34
-rw-r--r--tests/sva/sva_range.sv19
-rw-r--r--tests/sva/sva_throughout.sv19
-rwxr-xr-xtests/tools/autotest.sh4
-rw-r--r--tests/unit/Makefile35
-rw-r--r--tests/unit/kernel/logTest.cc14
-rw-r--r--tests/unit/kernel/rtlilTest.cc14
-rw-r--r--tests/various/reg_wire_error.sv74
-rw-r--r--tests/various/reg_wire_error.ys1
388 files changed, 29857 insertions, 4431 deletions
diff --git a/.github/issue_template.md b/.github/issue_template.md
new file mode 100644
index 00000000..24e91a4e
--- /dev/null
+++ b/.github/issue_template.md
@@ -0,0 +1,16 @@
+## Steps to reproduce the issue
+
+*Provide instructions for reproducing the issue. Make sure to include
+all neccessary source files. (You can simply drag&drop a .zip file into
+the issue editor.)*
+
+## Expected behavior
+
+*Please describe the behavior you would have expected from the tool.*
+
+## Actual behavior
+
+*Please describe how the behavior you see differs from the expected behavior.*
+
+**Important Note:** Nobody will be able to help you and/or fix the issue if you
+do not provide sufficient information for reproducing the problem.
diff --git a/.gitignore b/.gitignore
index 93e28cd6..48ce458c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,9 @@
*.o
*.d
.*.swp
+*.gch
+*.gcda
+*.gcno
/.cproject
/.project
/.settings
@@ -9,6 +12,8 @@
/qtcreator.config
/qtcreator.creator
/qtcreator.creator.user
+/coverage.info
+/coverage_html
/Makefile.conf
/abc
/viz.js
@@ -27,3 +32,6 @@
/yosys-win32-vcxsrc-*
/yosysjs-*
/libyosys.so
+/tests/unit/bintest/
+/tests/unit/objtest/
+/tests/ystests
diff --git a/.travis.yml b/.travis.yml
index 9f0cc06e..321c3325 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,34 +1,148 @@
sudo: false
-script: make && make test
language: cpp
-addons:
- apt:
- sources:
- - ubuntu-toolchain-r-test
- packages:
- - gperf
- - build-essential
- - clang
- - bison
- - flex
- - libreadline-dev
- - gawk
- - tcl-dev
- - libffi-dev
- - git
- - mercurial
- - graphviz
- - xdot
- - pkg-config
- - python
- - g++-4.8
+
+cache:
+ ccache: true
+ directories:
+ - ~/.local-bin
+
+
+env:
+ global:
+ - MAKEFLAGS="-j 2"
+
+matrix:
+ include:
+ # Latest gcc-4.8, earliest version supported by Travis
+ - os: linux
+ addons:
+ apt:
+ packages:
+ - g++-4.8
+ - gperf
+ - build-essential
+ - bison
+ - flex
+ - libreadline-dev
+ - gawk
+ - tcl-dev
+ - libffi-dev
+ - git
+ - graphviz
+ - xdot
+ - pkg-config
+ - python
+ env:
+ - MATRIX_EVAL="CONFIG=gcc && CC=gcc-4.8 && CXX=g++-4.8"
+
+ # Latest gcc-6 on Travis Linux
+ - os: linux
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - g++-6
+ - gperf
+ - build-essential
+ - bison
+ - flex
+ - libreadline-dev
+ - gawk
+ - tcl-dev
+ - libffi-dev
+ - git
+ - graphviz
+ - xdot
+ - pkg-config
+ - python
+ env:
+ - MATRIX_EVAL="CONFIG=gcc && CC=gcc-6 && CXX=g++-6"
+
+ # Latest gcc supported on Travis Linux
+ - os: linux
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - g++-7
+ - gperf
+ - build-essential
+ - bison
+ - flex
+ - libreadline-dev
+ - gawk
+ - tcl-dev
+ - libffi-dev
+ - git
+ - graphviz
+ - xdot
+ - pkg-config
+ - python
+ env:
+ - MATRIX_EVAL="CONFIG=gcc && CC=gcc-7 && CXX=g++-7"
+
+ # Clang which ships on Trusty Linux
+ - os: linux
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-precise-3.8
+ packages:
+ - clang-3.8
+ - gperf
+ - build-essential
+ - bison
+ - flex
+ - libreadline-dev
+ - gawk
+ - tcl-dev
+ - libffi-dev
+ - git
+ - graphviz
+ - xdot
+ - pkg-config
+ - python
+ env:
+ - MATRIX_EVAL="CONFIG=clang && CC=clang-3.8 && CXX=clang++-3.8"
+
+ # Latest clang supported by Travis Linux
+ - os: linux
+ addons:
+ apt:
+ sources:
+ - llvm-toolchain-trusty-5.0
+ packages:
+ - clang-5.0
+ - gperf
+ - build-essential
+ - bison
+ - flex
+ - libreadline-dev
+ - gawk
+ - tcl-dev
+ - libffi-dev
+ - git
+ - graphviz
+ - xdot
+ - pkg-config
+ - python
+ env:
+ - MATRIX_EVAL="CONFIG=clang && CC=clang-5.0 && CXX=clang++-5.0"
+
+ # Latest clang on Mac OS X
+ - os: osx
+ osx_image: xcode8
+ env:
+ - MATRIX_EVAL="CONFIG=gcc && CC=gcc-7 && CXX=g++-7"
+
before_install:
- - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
- - git clone git://github.com/steveicarus/iverilog.git
- - (cd iverilog && autoconf && ./configure --prefix=$HOME/iverilog && make && make install)
- - export PATH=$PATH:$HOME/iverilog/bin
-compiler:
-# - clang
- - gcc
-os:
- - linux
+ - ./.travis/setup.sh
+
+script:
+ - ./.travis/build-and-test.sh
+
+after_success:
+ - ./.travis/deploy-after-success.sh
diff --git a/.travis/build-and-test.sh b/.travis/build-and-test.sh
new file mode 100755
index 00000000..096dde64
--- /dev/null
+++ b/.travis/build-and-test.sh
@@ -0,0 +1,49 @@
+#! /bin/bash
+
+set -e
+
+source .travis/common.sh
+
+##########################################################################
+
+echo
+echo 'Configuring...' && echo -en 'travis_fold:start:script.configure\\r'
+echo
+
+if [ "$CONFIG" = "gcc" ]; then
+ echo "Configuring for gcc."
+ make config-gcc
+elif [ "$CONFIG" = "clang" ]; then
+ echo "Configuring for clang."
+ make config-clang
+fi
+
+echo
+echo -en 'travis_fold:end:script.configure\\r'
+echo
+
+##########################################################################
+
+echo
+echo 'Building...' && echo -en 'travis_fold:start:script.build\\r'
+echo
+
+make
+
+echo
+echo -en 'travis_fold:end:script.build\\r'
+echo
+
+##########################################################################
+
+echo
+echo 'Testing...' && echo -en 'travis_fold:start:script.test\\r'
+echo
+
+make test
+
+echo
+echo -en 'travis_fold:end:script.test\\r'
+echo
+
+##########################################################################
diff --git a/.travis/common.sh b/.travis/common.sh
new file mode 100644
index 00000000..8eecc4c0
--- /dev/null
+++ b/.travis/common.sh
@@ -0,0 +1,15 @@
+#! /bin/bash
+
+# Setup the CC / CXX from the matrix config
+eval "${MATRIX_EVAL}"
+
+# Look for location binaries first
+export PATH="$HOME/.local-bin/bin:$PATH"
+
+# OS X specific common setup
+if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+ export PATH="/usr/local/opt/ccache/libexec:$PATH"
+fi
+
+# Parallel builds!
+MAKEFLAGS="-j 2"
diff --git a/.travis/deploy-after-success.sh b/.travis/deploy-after-success.sh
new file mode 100755
index 00000000..d64e9524
--- /dev/null
+++ b/.travis/deploy-after-success.sh
@@ -0,0 +1,6 @@
+#! /bin/bash
+
+set -x
+set -e
+
+# FIXME: Upload the build results somewhere...
diff --git a/.travis/setup.sh b/.travis/setup.sh
new file mode 100755
index 00000000..06851578
--- /dev/null
+++ b/.travis/setup.sh
@@ -0,0 +1,97 @@
+#! /bin/bash
+
+set -e
+
+source .travis/common.sh
+
+##########################################################################
+
+# Fixing Travis's git clone
+echo
+echo 'Fixing git setup...' && echo -en 'travis_fold:start:before_install.git\\r'
+echo
+git fetch --unshallow && git fetch --tags
+
+# For pull requests, we get more info about the git source.
+if [ z"$TRAVIS_PULL_REQUEST_SLUG" != z ]; then
+ echo "- Fetching from pull request source"
+ git remote add source https://github.com/$TRAVIS_PULL_REQUEST_SLUG.git
+ git fetch source && git fetch --tags
+
+ echo "- Fetching the actual pull request"
+ git fetch origin pull/$TRAVIS_PULL_REQUEST/head:pull-$TRAVIS_PULL_REQUEST-head
+ git fetch origin pull/$TRAVIS_PULL_REQUEST/merge:pull-$TRAVIS_PULL_REQUEST-merge
+
+ git log -n 5 --graph pull-$TRAVIS_PULL_REQUEST-merge
+fi
+
+# For building branches we need to fix the "detached head" state.
+if [ z"$TRAVIS_BRANCH" != z ]; then
+ TRAVIS_COMMIT_ACTUAL=$(git log --pretty=format:'%H' -n 1)
+ echo "- Fixing detached head (current $TRAVIS_COMMIT_ACTUAL -> $TRAVIS_COMMIT)"
+ git remote -v
+ git branch -v
+ if [ x"$(git show-ref -s HEAD)" = x"$TRAVIS_COMMIT" ]; then
+ echo "Checked out at $TRAVIS_COMMIT"
+ else
+ if [ z"$TRAVIS_PULL_REQUEST_SLUG" != z ]; then
+ git fetch source $TRAVIS_COMMIT || echo "Unable to fetch $TRAVIS_COMMIT from source"
+ fi
+ git fetch origin $TRAVIS_COMMIT || echo "Unable to fetch $TRAVIS_COMMIT from origin"
+ fi
+ git branch -D $TRAVIS_BRANCH || true
+ git checkout $TRAVIS_COMMIT -b $TRAVIS_BRANCH
+ git branch -v
+fi
+
+# Output status information.
+git status
+git describe --tags
+git log -n 5 --graph
+echo
+echo -en 'travis_fold:end:before_install.git\\r'
+echo
+
+##########################################################################
+
+# Mac OS X specific setup.
+if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+ (
+ echo
+ echo 'Setting up brew...' && echo -en 'travis_fold:start:before_install.brew\\r'
+ echo
+ brew update
+ brew tap Homebrew/bundle
+ brew bundle
+ brew install ccache
+ brew install gcc@7
+ echo
+ echo -en 'travis_fold:end:before_install.brew\\r'
+ echo
+ )
+fi
+
+##########################################################################
+
+# Install iverilog
+(
+ if [ ! -e ~/.local-bin/bin/iverilog ]; then
+ echo
+ echo 'Building iverilog...' && echo -en 'travis_fold:start:before_install.iverilog\\r'
+ echo
+ mkdir -p ~/.local-src
+ mkdir -p ~/.local-bin
+ cd ~/.local-src
+ git clone git://github.com/steveicarus/iverilog.git
+ cd iverilog
+ autoconf
+ ./configure --prefix=$HOME/.local-bin
+ make
+ make install
+ echo
+ echo -en 'travis_fold:end:before_install.iverilog\\r'
+ echo
+ fi
+)
+
+##########################################################################
diff --git a/Brewfile b/Brewfile
new file mode 100644
index 00000000..0c58ce16
--- /dev/null
+++ b/Brewfile
@@ -0,0 +1,8 @@
+brew "bison"
+brew "flex"
+brew "gawk"
+brew "libffi"
+brew "git"
+brew "graphviz"
+brew "pkg-config"
+brew "python3"
diff --git a/CHANGELOG b/CHANGELOG
index bfea999a..01c78ab3 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -3,6 +3,19 @@ List of major changes and improvements between releases
=======================================================
+Yosys 0.7 .. Yosys ???
+----------------------
+
+ * MAX10 and Cyclone IV Support
+ - Added initial version of metacommand "synth_intel".
+ - Improved write_verilog command to produce VQM netlist for Quartus Prime.
+ - Added support for MAX10 FPGA family synthesis.
+ - Added support for Cyclone IV family synthesis.
+ - Added example of implementation for DE2i-150 board.
+ - Added example of implementation for MAX10 development kit.
+ - Added LFSR example from Asic World.
+
+
Yosys 0.6 .. Yosys 0.7
----------------------
diff --git a/COPYING b/COPYING
new file mode 100644
index 00000000..a01b7b69
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,13 @@
+Copyright (C) 2012 - 2017 Clifford Wolf <clifford@clifford.at>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/CodingReadme b/CodingReadme
index cbe1fb8b..b64e7917 100644
--- a/CodingReadme
+++ b/CodingReadme
@@ -21,7 +21,7 @@ Here is a the C++ code for a "hello_world" Yosys command (hello.cc):
struct HelloWorldPass : public Pass {
HelloWorldPass() : Pass("hello_world") { }
- virtual void execute(vector<string>, Design*) {
+ void execute(vector<string>, Design*) override {
log("Hello World!\n");
}
} HelloWorldPass;
@@ -373,6 +373,7 @@ Finally run all tests with "make config-{clang,gcc,gcc-4.8}":
cd ~yosys
make clean
make test
+ make ystests
make vloghtb
make install
@@ -411,3 +412,98 @@ Updating the website:
git commit -am update
make push
+
+
+Cross-Building for Windows with MXE
+===================================
+
+Check http://mxe.cc/#requirements and install all missing requirements.
+
+As root (or other user with write access to /usr/local/src):
+
+ cd /usr/local/src
+ git clone https://github.com/mxe/mxe.git
+ cd mxe
+
+ make -j$(nproc) MXE_PLUGIN_DIRS="plugins/tcl.tk" \
+ MXE_TARGETS="i686-w64-mingw32.static" \
+ gcc tcl readline
+
+Then as regular user in some directory where you build stuff:
+
+ git clone https://github.com/cliffordwolf/yosys.git yosys-win32
+ cd yosys-win32
+ make config-mxe
+ make -j$(nproc) mxebin
+
+
+
+How to add unit test
+====================
+
+Unit test brings some advantages, briefly, we can list some of them (reference
+[1](https://en.wikipedia.org/wiki/Unit_testing)):
+
+* Tests reduce bugs in new features;
+* Tests reduce bugs in existing features;
+* Tests are good documentation;
+* Tests reduce the cost of change;
+* Tests allow refactoring;
+
+With those advantages in mind, it was required to choose a framework which fits
+well with C/C++ code. Hence, it was chosen (google test)
+[https://github.com/google/googletest], because it is largely used and it is
+relatively easy learn.
+
+Install and configure google test (manually)
+--------------------------------------------
+
+In this section, you will see a brief description of how to install google
+test. However, it is strongly recommended that you take a look to the official
+repository (https://github.com/google/googletest) and refers to that if you
+have any problem to install it. Follow the steps below:
+
+* Install: cmake and pthread
+* Clone google test project from: https://github.com/google/googletest and
+ enter in the project directory
+* Inside project directory, type:
+
+```
+cmake -DBUILD_SHARED_LIBS=ON .
+make
+```
+
+* After compilation, copy all "*.so" inside directory "googlemock" and
+ "googlemock/gtest" to "/usr/lib/"
+* Done! Now you can compile your tests.
+
+If you have any problem, go to the official repository to find help.
+
+Ps.: Some distros already have googletest packed. If your distro supports it,
+you can use it instead of compile.
+
+Create new unit test
+--------------------
+
+If you want to add new unit tests for Yosys, just follow the steps below:
+
+* Go to directory "yosys/test/unit/"
+* In this directory you can find something similar Yosys's directory structure.
+ To create your unit test file you have to follow this pattern:
+ fileNameToImplementUnitTest + Test.cc. E.g.: if you want to implement the
+ unit test for kernel/celledges.cc, you will need to create a file like this:
+ tests/unit/kernel/celledgesTest.cc;
+* Implement your unit test
+
+Run unit test
+-------------
+
+To compile and run all unit tests, just go to yosys root directory and type:
+```
+make unit-test
+```
+
+If you want to remove all unit test files, type:
+```
+make clean-unit-test
+```
diff --git a/Makefile b/Makefile
index 0a61fe65..7698047e 100644
--- a/Makefile
+++ b/Makefile
@@ -5,19 +5,29 @@ CONFIG := clang
# CONFIG := emcc
# CONFIG := mxe
# CONFIG := msys2
+# CONFIG := msys2-64
# features (the more the better)
ENABLE_TCL := 1
ENABLE_ABC := 1
ENABLE_PLUGINS := 1
ENABLE_READLINE := 1
+ENABLE_EDITLINE := 0
ENABLE_VERIFIC := 0
ENABLE_COVER := 1
ENABLE_LIBYOSYS := 0
+ENABLE_PROTOBUF := 0
# other configuration flags
+ENABLE_GCOV := 0
ENABLE_GPROF := 0
+ENABLE_DEBUG := 0
ENABLE_NDEBUG := 0
+LINK_CURSES := 0
+LINK_TERMCAP := 0
+LINK_ABC := 0
+# Needed for environments that don't have proper thread support (i.e. emscripten)
+DISABLE_ABC_THREADS := 0
# clang sanitizers
SANITIZER =
@@ -27,6 +37,7 @@ SANITIZER =
# SANITIZER = cfi
+OS := $(shell uname -s)
PREFIX ?= /usr/local
INSTALL_SUDO :=
@@ -44,35 +55,51 @@ TARGETS = yosys$(EXE) yosys-config
PRETTY = 1
SMALL = 0
+# Unit test
+UNITESTPATH := tests/unit
+
all: top-all
YOSYS_SRC := $(dir $(firstword $(MAKEFILE_LIST)))
VPATH := $(YOSYS_SRC)
-CXXFLAGS += -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -D_YOSYS_ -fPIC -I$(PREFIX)/include
-LDFLAGS += -L$(LIBDIR)
-LDLIBS = -lstdc++ -lm
-
-PKG_CONFIG = pkg-config
-SED = sed
-BISON = bison
-
-ifeq (Darwin,$(findstring Darwin,$(shell uname)))
- # add macports/homebrew include and library path to search directories, don't use '-rdynamic' and '-lrt':
- CXXFLAGS += -I/opt/local/include -I/usr/local/opt/readline/include
- LDFLAGS += -L/opt/local/lib -L/usr/local/opt/readline/lib
- # add homebrew's libffi include and library path
- CXXFLAGS += $(shell PKG_CONFIG_PATH=$$(brew list libffi | grep pkgconfig | xargs dirname) pkg-config --silence-errors --cflags libffi)
- LDFLAGS += $(shell PKG_CONFIG_PATH=$$(brew list libffi | grep pkgconfig | xargs dirname) pkg-config --silence-errors --libs libffi)
- # use bison installed by homebrew if available
- BISON = $(shell (brew list bison | grep -m1 "bin/bison") || echo bison)
- SED = sed
+CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -D_YOSYS_ -fPIC -I$(PREFIX)/include
+LDFLAGS := $(LDFLAGS) -L$(LIBDIR)
+LDLIBS := $(LDLIBS) -lstdc++ -lm
+PLUGIN_LDFLAGS :=
+
+PKG_CONFIG ?= pkg-config
+SED ?= sed
+BISON ?= bison
+STRIP ?= strip
+
+ifeq ($(OS), Darwin)
+PLUGIN_LDFLAGS += -undefined dynamic_lookup
+
+# homebrew search paths
+ifneq ($(shell which brew),)
+BREW_PREFIX := $(shell brew --prefix)/opt
+CXXFLAGS += -I$(BREW_PREFIX)/readline/include
+LDFLAGS += -L$(BREW_PREFIX)/readline/lib
+PKG_CONFIG_PATH := $(BREW_PREFIX)/libffi/lib/pkgconfig:$(PKG_CONFIG_PATH)
+PKG_CONFIG_PATH := $(BREW_PREFIX)/tcl-tk/lib/pkgconfig:$(PKG_CONFIG_PATH)
+export PATH := $(BREW_PREFIX)/bison/bin:$(BREW_PREFIX)/gettext/bin:$(BREW_PREFIX)/flex/bin:$(PATH)
+
+# macports search paths
+else ifneq ($(shell which port),)
+PORT_PREFIX := $(patsubst %/bin/port,%,$(shell which port))
+CXXFLAGS += -I$(PORT_PREFIX)/include
+LDFLAGS += -L$(PORT_PREFIX)/lib
+PKG_CONFIG_PATH := $(PORT_PREFIX)/lib/pkgconfig:$(PKG_CONFIG_PATH)
+export PATH := $(PORT_PREFIX)/bin:$(PATH)
+endif
+
else
- LDFLAGS += -rdynamic
- LDLIBS += -lrt
+LDFLAGS += -rdynamic
+LDLIBS += -lrt
endif
-YOSYS_VER := 0.7
+YOSYS_VER := 0.7+$(shell cd $(YOSYS_SRC) && test -e .git && { git log --author=clifford@clifford.at --oneline 61f6811.. | wc -l; })
GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
OBJS = kernel/version_$(GIT_REV).o
@@ -82,10 +109,10 @@ OBJS = kernel/version_$(GIT_REV).o
# is just a symlink to your actual ABC working directory, as 'make mrproper'
# will remove the 'abc' directory and you do not want to accidentally
# delete your work on ABC..
-ABCREV = eb6eca6807cc
+ABCREV = ae6716b
ABCPULL = 1
-ABCURL ?= https://bitbucket.org/alanmi/abc
-ABCMKARGS = CC="$(CXX)" CXX="$(CXX)"
+ABCURL ?= https://github.com/berkeley-abc/abc
+ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1
# set ABCEXTERNAL = <abc-command> to use an external ABC instance
# Note: The in-tree ABC (yosys-abc) will not be installed when ABCEXTERNAL is set.
@@ -105,6 +132,7 @@ ifeq ($(CONFIG),clang)
CXX = clang
LD = clang++
CXXFLAGS += -std=c++11 -Os
+ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
ifneq ($(SANITIZER),)
$(info [Clang Sanitizer] $(SANITIZER))
@@ -127,16 +155,31 @@ else ifeq ($(CONFIG),gcc)
CXX = gcc
LD = gcc
CXXFLAGS += -std=c++11 -Os
+ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
+
+else ifeq ($(CONFIG),gcc-static)
+LD = $(CXX)
+LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -static
+LDLIBS := $(filter-out -lrt,$(LDLIBS))
+CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
+CXXFLAGS += -std=c++11 -Os
+ABCMKARGS = CC="$(CC)" CXX="$(CXX)" LD="$(LD)" ABC_USE_LIBSTDCXX=1 LIBS="-lm -lpthread -static" OPTFLAGS="-O" \
+ ARCHFLAGS="-DABC_USE_STDINT_H -DABC_NO_DYNAMIC_LINKING=1 -Wno-unused-but-set-variable $(ARCHFLAGS)" ABC_USE_NO_READLINE=1
+ifeq ($(DISABLE_ABC_THREADS),1)
+ABCMKARGS += "ABC_USE_NO_PTHREADS=1"
+endif
else ifeq ($(CONFIG),gcc-4.8)
CXX = gcc-4.8
LD = gcc-4.8
CXXFLAGS += -std=c++11 -Os
+ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
else ifeq ($(CONFIG),emcc)
CXX = emcc
LD = emcc
CXXFLAGS := -std=c++11 $(filter-out -fPIC -ggdb,$(CXXFLAGS))
+ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DABC_MEMALIGN=8"
EMCCFLAGS := -Os -Wno-warn-absolute-paths
EMCCFLAGS += --memory-init-file 0 --embed-file share -s NO_EXIT_RUNTIME=1
EMCCFLAGS += -s EXPORTED_FUNCTIONS="['_main','_run','_prompt','_errmsg']"
@@ -150,6 +193,11 @@ EXE = .js
TARGETS := $(filter-out yosys-config,$(TARGETS))
EXTRA_TARGETS += yosysjs-$(YOSYS_VER).zip
+ifeq ($(ENABLE_ABC),1)
+LINK_ABC := 1
+DISABLE_ABC_THREADS := 1
+endif
+
viz.js:
wget -O viz.js.part https://github.com/mdaines/viz.js/releases/download/0.0.3/viz.js
mv viz.js.part viz.js
@@ -164,29 +212,41 @@ yosys.html: misc/yosys.html
$(P) cp misc/yosys.html yosys.html
else ifeq ($(CONFIG),mxe)
-CXX = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc
-LD = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc
-CXXFLAGS += -std=c++11 -Os -D_POSIX_SOURCE
+PKG_CONFIG = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-pkg-config
+CXX = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-g++
+LD = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-g++
+CXXFLAGS += -std=c++11 -Os -D_POSIX_SOURCE -DYOSYS_MXE_HACKS -Wno-attributes
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
LDLIBS := $(filter-out -lrt,$(LDLIBS))
-ABCMKARGS += ARCHFLAGS="-DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 -DSIZEOF_INT=4 -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -x c++ -fpermissive -w"
-ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=1 CC="$(CXX)" CXX="$(CXX)"
+ABCMKARGS += ARCHFLAGS="-DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
+ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=1 CC="/usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc"
EXE = .exe
else ifeq ($(CONFIG),msys2)
-CXX = i686-w64-mingw32-gcc
-LD = i686-w64-mingw32-gcc
+CXX = i686-w64-mingw32-g++
+LD = i686-w64-mingw32-g++
CXXFLAGS += -std=c++11 -Os -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
LDLIBS := $(filter-out -lrt,$(LDLIBS))
-ABCMKARGS += ARCHFLAGS="-DSIZEOF_VOID_P=4 -DSIZEOF_LONG=4 -DSIZEOF_INT=4 -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -x c++ -fpermissive -w"
-ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" ABC_USE_NO_READLINE=0 CC="$(CXX)" CXX="$(CXX)"
+ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
+ABCMKARGS += LIBS="-lpthread -s" ABC_USE_NO_READLINE=0 CC="i686-w64-mingw32-gcc" CXX="$(CXX)"
+EXE = .exe
+
+else ifeq ($(CONFIG),msys2-64)
+CXX = x86_64-w64-mingw32-g++
+LD = x86_64-w64-mingw32-g++
+CXXFLAGS += -std=c++11 -Os -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR
+CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
+LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
+LDLIBS := $(filter-out -lrt,$(LDLIBS))
+ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w"
+ABCMKARGS += LIBS="-lpthread -s" ABC_USE_NO_READLINE=0 CC="x86_64-w64-mingw32-gcc" CXX="$(CXX)"
EXE = .exe
else ifneq ($(CONFIG),none)
-$(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, gcc-4.8, emcc, mxe, msys2)
+$(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, gcc-4.8, emcc, mxe, msys2, msys2-64)
endif
ifeq ($(ENABLE_LIBYOSYS),1)
@@ -195,22 +255,67 @@ endif
ifeq ($(ENABLE_READLINE),1)
CXXFLAGS += -DYOSYS_ENABLE_READLINE
+ifeq ($(OS), FreeBSD)
+CXXFLAGS += -I/usr/local/include
+endif
LDLIBS += -lreadline
+ifeq ($(LINK_CURSES),1)
+LDLIBS += -lcurses
+ABCMKARGS += "ABC_READLINE_LIBRARIES=-lcurses -lreadline"
+endif
+ifeq ($(LINK_TERMCAP),1)
+LDLIBS += -ltermcap
+ABCMKARGS += "ABC_READLINE_LIBRARIES=-lreadline -ltermcap"
+endif
ifeq ($(CONFIG),mxe)
-LDLIBS += -lpdcurses
+LDLIBS += -ltermcap
+endif
+else
+ifeq ($(ENABLE_EDITLINE),1)
+CXXFLAGS += -DYOSYS_ENABLE_EDITLINE
+LDLIBS += -ledit -ltinfo -lbsd
+else
+ABCMKARGS += "ABC_USE_NO_READLINE=1"
endif
endif
+ifeq ($(DISABLE_ABC_THREADS),1)
+ABCMKARGS += "ABC_USE_NO_PTHREADS=1"
+endif
+
ifeq ($(ENABLE_PLUGINS),1)
-CXXFLAGS += -DYOSYS_ENABLE_PLUGINS $(shell $(PKG_CONFIG) --silence-errors --cflags libffi)
-LDLIBS += $(shell $(PKG_CONFIG) --silence-errors --libs libffi || echo -lffi) -ldl
+CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags libffi) -DYOSYS_ENABLE_PLUGINS
+LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs libffi || echo -lffi)
+ifneq ($(OS), FreeBSD)
+LDLIBS += -ldl
+endif
endif
ifeq ($(ENABLE_TCL),1)
TCL_VERSION ?= tcl$(shell bash -c "tclsh <(echo 'puts [info tclversion]')")
+ifeq ($(OS), FreeBSD)
+TCL_INCLUDE ?= /usr/local/include/$(TCL_VERSION)
+else
TCL_INCLUDE ?= /usr/include/$(TCL_VERSION)
-CXXFLAGS += -I$(TCL_INCLUDE) -DYOSYS_ENABLE_TCL
-LDLIBS += -l$(TCL_VERSION)
+endif
+
+ifeq ($(CONFIG),mxe)
+CXXFLAGS += -DYOSYS_ENABLE_TCL
+LDLIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz
+else
+CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL
+ifeq ($(OS), FreeBSD)
+# FreeBSD uses tcl8.6, but lib is named "libtcl86"
+LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs tcl || echo -l$(TCL_VERSION) | tr -d '.')
+else
+LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs tcl || echo -l$(TCL_VERSION))
+endif
+endif
+endif
+
+ifeq ($(ENABLE_GCOV),1)
+CXXFLAGS += --coverage
+LDFLAGS += --coverage
endif
ifeq ($(ENABLE_GPROF),1)
@@ -219,21 +324,40 @@ LDFLAGS += -pg
endif
ifeq ($(ENABLE_NDEBUG),1)
-CXXFLAGS := -O3 -DNDEBUG $(filter-out -Os,$(CXXFLAGS))
+CXXFLAGS := -O3 -DNDEBUG $(filter-out -Os -ggdb,$(CXXFLAGS))
+endif
+
+ifeq ($(ENABLE_DEBUG),1)
+ifeq ($(CONFIG),clang)
+CXXFLAGS := -O0 -DDEBUG $(filter-out -Os,$(CXXFLAGS))
+else
+CXXFLAGS := -Og -DDEBUG $(filter-out -Os,$(CXXFLAGS))
+endif
endif
ifeq ($(ENABLE_ABC),1)
CXXFLAGS += -DYOSYS_ENABLE_ABC
+ifeq ($(LINK_ABC),1)
+CXXFLAGS += -DYOSYS_LINK_ABC
+ifeq ($(DISABLE_ABC_THREADS),0)
+LDLIBS += -lpthread
+endif
+else
ifeq ($(ABCEXTERNAL),)
TARGETS += yosys-abc$(EXE)
endif
endif
+endif
ifeq ($(ENABLE_VERIFIC),1)
VERIFIC_DIR ?= /usr/local/src/verific_lib_eval
-VERIFIC_COMPONENTS ?= verilog vhdl database util containers sdf
+VERIFIC_COMPONENTS ?= verilog vhdl database util containers sdf hier_tree
CXXFLAGS += $(patsubst %,-I$(VERIFIC_DIR)/%,$(VERIFIC_COMPONENTS)) -DYOSYS_ENABLE_VERIFIC
-LDLIBS += $(patsubst %,$(VERIFIC_DIR)/%/*-linux.a,$(VERIFIC_COMPONENTS))
+LDLIBS += $(patsubst %,$(VERIFIC_DIR)/%/*-linux.a,$(VERIFIC_COMPONENTS)) -lz
+endif
+
+ifeq ($(ENABLE_PROTOBUF),1)
+LDLIBS += $(shell pkg-config --cflags --libs protobuf)
endif
ifeq ($(ENABLE_COVER),1)
@@ -347,6 +471,10 @@ include techlibs/common/Makefile.inc
endif
+ifeq ($(LINK_ABC),1)
+OBJS += yosys-libabc.a
+endif
+
top-all: $(TARGETS) $(EXTRA_TARGETS)
@echo ""
@echo " Build successful."
@@ -377,35 +505,50 @@ kernel/version_$(GIT_REV).cc: $(YOSYS_SRC)/Makefile
$(P) rm -f kernel/version_*.o kernel/version_*.d kernel/version_*.cc
$(Q) mkdir -p kernel && echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"$(YOSYS_VER_STR)\"; }" > kernel/version_$(GIT_REV).cc
+ifeq ($(ENABLE_VERIFIC),1)
+CXXFLAGS_NOVERIFIC = $(foreach v,$(CXXFLAGS),$(if $(findstring $(VERIFIC_DIR),$(v)),,$(v)))
+LDLIBS_NOVERIFIC = $(foreach v,$(LDLIBS),$(if $(findstring $(VERIFIC_DIR),$(v)),,$(v)))
+else
+CXXFLAGS_NOVERIFIC = $(CXXFLAGS)
+LDLIBS_NOVERIFIC = $(LDLIBS)
+endif
+
yosys-config: misc/yosys-config.in
- $(P) $(SED) -e 's#@CXXFLAGS@#$(subst -I. -I"$(YOSYS_SRC)",-I"$(DATDIR)/include",$(CXXFLAGS))#;' \
- -e 's#@CXX@#$(CXX)#;' -e 's#@LDFLAGS@#$(LDFLAGS)#;' -e 's#@LDLIBS@#$(LDLIBS)#;' \
- -e 's#@BINDIR@#$(BINDIR)#;' -e 's#@DATDIR@#$(DATDIR)#;' < $< > yosys-config
+ $(P) $(SED) -e 's#@CXXFLAGS@#$(subst -I. -I"$(YOSYS_SRC)",-I"$(DATDIR)/include",$(strip $(CXXFLAGS_NOVERIFIC)))#;' \
+ -e 's#@CXX@#$(strip $(CXX))#;' -e 's#@LDFLAGS@#$(strip $(LDFLAGS) $(PLUGIN_LDFLAGS))#;' -e 's#@LDLIBS@#$(strip $(LDLIBS_NOVERIFIC))#;' \
+ -e 's#@BINDIR@#$(strip $(BINDIR))#;' -e 's#@DATDIR@#$(strip $(DATDIR))#;' < $< > yosys-config
$(Q) chmod +x yosys-config
-abc/abc-$(ABCREV)$(EXE):
+abc/abc-$(ABCREV)$(EXE) abc/libabc-$(ABCREV).a:
$(P)
ifneq ($(ABCREV),default)
- $(Q) if ( cd abc 2> /dev/null && hg identify; ) | grep -q +; then \
+ $(Q) if test -d abc/.hg; then \
+ echo 'REEBE: NOP qverpgbel vf n ut jbexvat pbcl! Erzbir nop/ naq er-eha "znxr".' | tr 'A-Za-z' 'N-ZA-Mn-za-m'; false; \
+ fi
+ $(Q) if ( cd abc 2> /dev/null && ! git diff-index --quiet HEAD; ); then \
echo 'REEBE: NOP pbagnvaf ybpny zbqvsvpngvbaf! Frg NOPERI=qrsnhyg va Lbflf Znxrsvyr!' | tr 'A-Za-z' 'N-ZA-Mn-za-m'; false; \
fi
- $(Q) if test "`cd abc 2> /dev/null && hg identify | cut -f1 -d' '`" != "$(ABCREV)"; then \
+ $(Q) if test "`cd abc 2> /dev/null && git rev-parse --short HEAD`" != "$(ABCREV)"; then \
test $(ABCPULL) -ne 0 || { echo 'REEBE: NOP abg hc gb qngr naq NOPCHYY frg gb 0 va Znxrsvyr!' | tr 'A-Za-z' 'N-ZA-Mn-za-m'; exit 1; }; \
echo "Pulling ABC from $(ABCURL):"; set -x; \
- test -d abc || hg clone $(ABCURL) abc; \
- cd abc && $(MAKE) DEP= clean && hg pull && hg update -r $(ABCREV); \
+ test -d abc || git clone $(ABCURL) abc; \
+ cd abc && $(MAKE) DEP= clean && git fetch origin master && git checkout $(ABCREV); \
fi
endif
$(Q) rm -f abc/abc-[0-9a-f]*
- $(Q) cd abc && $(MAKE) $(S) $(ABCMKARGS) PROG="abc-$(ABCREV)$(EXE)" MSG_PREFIX="$(eval P_OFFSET = 5)$(call P_SHOW)$(eval P_OFFSET = 10) ABC: "
+ $(Q) cd abc && $(MAKE) $(S) $(ABCMKARGS) $(if $(filter %.a,$@),PROG="abc-$(ABCREV)",PROG="abc-$(ABCREV)$(EXE)") MSG_PREFIX="$(eval P_OFFSET = 5)$(call P_SHOW)$(eval P_OFFSET = 10) ABC: " $(if $(filter %.a,$@),libabc-$(ABCREV).a)
ifeq ($(ABCREV),default)
.PHONY: abc/abc-$(ABCREV)$(EXE)
+.PHONY: abc/libabc-$(ABCREV).a
endif
yosys-abc$(EXE): abc/abc-$(ABCREV)$(EXE)
$(P) cp abc/abc-$(ABCREV)$(EXE) yosys-abc$(EXE)
+yosys-libabc.a: abc/libabc-$(ABCREV).a
+ $(P) cp abc/libabc-$(ABCREV).a yosys-libabc.a
+
ifneq ($(SEED),)
SEEDOPT="-S $(SEED)"
else
@@ -442,18 +585,44 @@ vloghtb: $(TARGETS) $(EXTRA_TARGETS)
@echo " Passed \"make vloghtb\"."
@echo ""
+ystests: $(TARGETS) $(EXTRA_TARGETS)
+ rm -rf tests/ystests
+ git clone https://github.com/YosysHQ/yosys-tests.git tests/ystests
+ +PATH="$$PWD:$$PATH" cd tests/ystests && $(MAKE)
+ @echo ""
+ @echo " Finished \"make ystests\"."
+ @echo ""
+
+# Unit test
+unit-test: libyosys.so
+ @$(MAKE) -C $(UNITESTPATH) CXX="$(CXX)" CPPFLAGS="$(CPPFLAGS)" \
+ CXXFLAGS="$(CXXFLAGS)" LDLIBS="$(LDLIBS)" ROOTPATH="$(CURDIR)"
+
+clean-unit-test:
+ @$(MAKE) -C $(UNITESTPATH) clean
+
install: $(TARGETS) $(EXTRA_TARGETS)
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR)
- $(INSTALL_SUDO) install $(TARGETS) $(DESTDIR)$(BINDIR)
+ $(INSTALL_SUDO) cp $(TARGETS) $(DESTDIR)$(BINDIR)
+ifneq ($(filter yosys,$(TARGETS)),)
+ $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/yosys
+endif
+ifneq ($(filter yosys-abc,$(TARGETS)),)
+ $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/yosys-abc
+endif
+ifneq ($(filter yosys-filterlib,$(TARGETS)),)
+ $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/yosys-filterlib
+endif
$(INSTALL_SUDO) mkdir -p $(DESTDIR)$(DATDIR)
$(INSTALL_SUDO) cp -r share/. $(DESTDIR)$(DATDIR)/.
ifeq ($(ENABLE_LIBYOSYS),1)
$(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(LIBDIR)
+ $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(LIBDIR)/libyosys.so
$(INSTALL_SUDO) ldconfig
endif
uninstall:
- $(INSTALL_SUDO) rm -vf $(addprefix $(DESTDIR)$(BINDIR),$(notdir $(TARGETS)))
+ $(INSTALL_SUDO) rm -vf $(addprefix $(DESTDIR)$(BINDIR)/,$(notdir $(TARGETS)))
$(INSTALL_SUDO) rm -rvf $(DESTDIR)$(DATDIR)
ifeq ($(ENABLE_LIBYOSYS),1)
$(INSTALL_SUDO) rm -vf $(DESTDIR)$(LIBDIR)/libyosys.so
@@ -471,16 +640,30 @@ clean:
rm -rf share
if test -d manual; then cd manual && sh clean.sh; fi
rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS)
- rm -f kernel/version_*.o kernel/version_*.cc abc/abc-[0-9a-f]*
+ rm -f kernel/version_*.o kernel/version_*.cc abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a
rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d
+ rm -rf tests/asicworld/*.out tests/asicworld/*.log
+ rm -rf tests/hana/*.out tests/hana/*.log
+ rm -rf tests/simple/*.out tests/simple/*.log
+ rm -rf tests/memories/*.out tests/memories/*.log tests/memories/*.dmp
+ rm -rf tests/sat/*.log tests/techmap/*.log tests/various/*.log
+ rm -rf tests/bram/temp tests/fsm/temp tests/realmath/temp tests/share/temp tests/smv/temp
+ rm -rf vloghtb/Makefile vloghtb/refdat vloghtb/rtl vloghtb/scripts vloghtb/spec vloghtb/check_yosys vloghtb/vloghammer_tb.tar.bz2 vloghtb/temp vloghtb/log_test_*
+ rm -f tests/tools/cmp_tbdata
clean-abc:
$(MAKE) -C abc DEP= clean
- rm -f yosys-abc$(EXE) abc/abc-[0-9a-f]*
+ rm -f yosys-abc$(EXE) yosys-libabc.a abc/abc-[0-9a-f]* abc/libabc-[0-9a-f]*.a
mrproper: clean
git clean -xdf
+coverage:
+ ./yosys -qp 'help; help -all'
+ rm -rf coverage.info coverage_html
+ lcov --capture -d . --no-external -o coverage.info
+ genhtml coverage.info --output-directory coverage_html
+
qtcreator:
{ for file in $(basename $(OBJS)); do \
for prefix in cc y l; do if [ -f $${file}.$${prefix} ]; then echo $$file.$${prefix}; fi; done \
@@ -520,6 +703,12 @@ config-clang: clean
config-gcc: clean
echo 'CONFIG := gcc' > Makefile.conf
+config-gcc-static: clean
+ echo 'CONFIG := gcc-static' > Makefile.conf
+ echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
+ echo 'ENABLE_READLINE := 0' >> Makefile.conf
+ echo 'ENABLE_TCL := 0' >> Makefile.conf
+
config-gcc-4.8: clean
echo 'CONFIG := gcc-4.8' > Makefile.conf
@@ -532,13 +721,19 @@ config-emcc: clean
config-mxe: clean
echo 'CONFIG := mxe' > Makefile.conf
- echo 'ENABLE_TCL := 0' >> Makefile.conf
echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
- echo 'ENABLE_READLINE := 0' >> Makefile.conf
config-msys2: clean
echo 'CONFIG := msys2' > Makefile.conf
+config-msys2-64: clean
+ echo 'CONFIG := msys2-64' > Makefile.conf
+
+config-gcov: clean
+ echo 'CONFIG := gcc' > Makefile.conf
+ echo 'ENABLE_GCOV := 1' >> Makefile.conf
+ echo 'ENABLE_DEBUG := 1' >> Makefile.conf
+
config-gprof: clean
echo 'CONFIG := gcc' > Makefile.conf
echo 'ENABLE_GPROF := 1' >> Makefile.conf
@@ -559,6 +754,6 @@ echo-git-rev:
-include kernel/*.d
-include techlibs/*/*.d
-.PHONY: all top-all abc test install install-abc manual clean mrproper qtcreator
-.PHONY: config-clean config-clang config-gcc config-gcc-4.8 config-gprof config-sudo
+.PHONY: all top-all abc test install install-abc manual clean mrproper qtcreator coverage vcxsrc mxebin
+.PHONY: config-clean config-clang config-gcc config-gcc-static config-gcc-4.8 config-gprof config-sudo
diff --git a/README b/README.md
index 8e43d444..424d9bbf 100644
--- a/README
+++ b/README.md
@@ -1,26 +1,23 @@
+```
+yosys -- Yosys Open SYnthesis Suite
- /-----------------------------------------------------------------------------\
- | |
- | yosys -- Yosys Open SYnthesis Suite |
- | |
- | Copyright (C) 2012 - 2016 Clifford Wolf <clifford@clifford.at> |
- | |
- | Permission to use, copy, modify, and/or distribute this software for any |
- | purpose with or without fee is hereby granted, provided that the above |
- | copyright notice and this permission notice appear in all copies. |
- | |
- | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
- | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
- | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
- | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
- | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
- | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
- | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
- | |
- \-----------------------------------------------------------------------------/
+Copyright (C) 2012 - 2017 Clifford Wolf <clifford@clifford.at>
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
-yosys -- Yosys Open SYnthesis Suite
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+```
+
+
+yosys – Yosys Open SYnthesis Suite
===================================
This is a framework for RTL synthesis tools. It currently has
@@ -41,29 +38,40 @@ Web Site
========
More information and documentation can be found on the Yosys web site:
+http://www.clifford.at/yosys/
- http://www.clifford.at/yosys/
-
-
-Getting Started
-===============
+Setup
+======
You need a C++ compiler with C++11 support (up-to-date CLANG or GCC is
recommended) and some standard tools such as GNU Flex, GNU Bison, and GNU Make.
-TCL, readline and libffi are optional (see ENABLE_* settings in Makefile).
-Xdot (graphviz) is used by the "show" command in yosys to display schematics.
+TCL, readline and libffi are optional (see ``ENABLE_*`` settings in Makefile).
+Xdot (graphviz) is used by the ``show`` command in yosys to display schematics.
+
For example on Ubuntu Linux 16.04 LTS the following commands will install all
prerequisites for building yosys:
$ sudo apt-get install build-essential clang bison flex \
- libreadline-dev gawk tcl-dev libffi-dev git mercurial \
+ libreadline-dev gawk tcl-dev libffi-dev git \
graphviz xdot pkg-config python3
+Similarily, on Mac OS X MacPorts or Homebrew can be used to install dependencies:
+
+ $ brew tap Homebrew/bundle && brew bundle
+ $ sudo port install bison flex readline gawk libffi \
+ git graphviz pkgconfig python36
+
+On FreeBSD use the following command to install all prerequisites:
+
+ # pkg install bison flex readline gawk libffi\
+ git graphviz pkgconfig python3 python36 tcl-wrapper
+
+On FreeBSD system use gmake instead of make. To run tests use:
+ % MAKE=gmake CC=cc gmake test
+
There are also pre-compiled Yosys binary packages for Ubuntu and Win32 as well
as a source distribution for Visual Studio. Visit the Yosys download page for
-more information:
-
- http://www.clifford.at/yosys/download.html
+more information: http://www.clifford.at/yosys/download.html
To configure the build system to use a specific compiler, use one of
@@ -74,7 +82,7 @@ For other compilers and build configurations it might be
necessary to make some changes to the config section of the
Makefile.
- $ vi Makefile ..or..
+ $ vi Makefile # ..or..
$ vi Makefile.conf
To build Yosys simply type 'make' in this directory.
@@ -86,6 +94,9 @@ To build Yosys simply type 'make' in this directory.
Note that this also downloads, builds and installs ABC (using yosys-abc
as executable name).
+Getting Started
+===============
+
Yosys can be used with the interactive command shell, with
synthesis scripts or with command line arguments. Let's perform
a simple synthesis job using the interactive command shell:
@@ -93,8 +104,8 @@ a simple synthesis job using the interactive command shell:
$ ./yosys
yosys>
-the command "help" can be used to print a list of all available
-commands and "help <command>" to print details on the specified command:
+the command ``help`` can be used to print a list of all available
+commands and ``help <command>`` to print details on the specified command:
yosys> help help
@@ -110,16 +121,16 @@ elaborate design hierarchy:
yosys> hierarchy
-convert processes ("always" blocks) to netlist elements and perform
+convert processes (``always`` blocks) to netlist elements and perform
some simple optimizations:
yosys> proc; opt
-display design netlist using xdot:
+display design netlist using ``xdot``:
yosys> show
-the same thing using 'gv' as postscript viewer:
+the same thing using ``gv`` as postscript viewer:
yosys> show -format ps -viewer gv
@@ -171,8 +182,8 @@ The following very basic synthesis script should work well with all designs:
techmap; opt
If ABC is enabled in the Yosys build configuration and a cell library is given
-in the liberty file mycells.lib, the following synthesis script will synthesize
-for the given cell library:
+in the liberty file ``mycells.lib``, the following synthesis script will
+synthesize for the given cell library:
# the high-level stuff
hierarchy; proc; fsm; opt; memory; opt
@@ -190,16 +201,17 @@ for the given cell library:
clean
If you do not have a liberty file but want to test this synthesis script,
-you can use the file examples/cmos/cmos_cells.lib from the yosys sources.
+you can use the file ``examples/cmos/cmos_cells.lib`` from the yosys sources.
Liberty file downloads for and information about free and open ASIC standard
cell libraries can be found here:
- http://www.vlsitechnology.org/html/libraries.html
- http://www.vlsitechnology.org/synopsys/vsclib013.lib
+- http://www.vlsitechnology.org/html/libraries.html
+- http://www.vlsitechnology.org/synopsys/vsclib013.lib
-The command "synth" provides a good default synthesis script (see "help synth").
-If possible a synthesis script should borrow from "synth". For example:
+The command ``synth`` provides a good default synthesis script (see
+``help synth``). If possible a synthesis script should borrow from ``synth``.
+For example:
# the high-level stuff
hierarchy
@@ -224,11 +236,11 @@ for them:
- Non-synthesizable language features as defined in
IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002
-- The "tri", "triand", "trior", "wand" and "wor" net types
+- The ``tri``, ``triand``, ``trior``, ``wand`` and ``wor`` net types
-- The "config" keyword and library map files
+- The ``config`` keyword and library map files
-- The "disable", "primitive" and "specify" statements
+- The ``disable``, ``primitive`` and ``specify`` statements
- Latched logic (is synthesized as logic with feedback loops)
@@ -236,83 +248,83 @@ for them:
Verilog Attributes and non-standard features
============================================
-- The 'full_case' attribute on case statements is supported
- (also the non-standard "// synopsys full_case" directive)
+- The ``full_case`` attribute on case statements is supported
+ (also the non-standard ``// synopsys full_case`` directive)
-- The 'parallel_case' attribute on case statements is supported
- (also the non-standard "// synopsys parallel_case" directive)
+- The ``parallel_case`` attribute on case statements is supported
+ (also the non-standard ``// synopsys parallel_case`` directive)
-- The "// synopsys translate_off" and "// synopsys translate_on"
- directives are also supported (but the use of `ifdef .. `endif
+- The ``// synopsys translate_off`` and ``// synopsys translate_on``
+ directives are also supported (but the use of ``` `ifdef .. `endif ```
is strongly recommended instead).
-- The "nomem2reg" attribute on modules or arrays prohibits the
+- The ``nomem2reg`` attribute on modules or arrays prohibits the
automatic early conversion of arrays to separate registers. This
is potentially dangerous. Usually the front-end has good reasons
for converting an array to a list of registers. Prohibiting this
step will likely result in incorrect synthesis results.
-- The "mem2reg" attribute on modules or arrays forces the early
+- The ``mem2reg`` attribute on modules or arrays forces the early
conversion of arrays to separate registers.
-- The "nomeminit" attribute on modules or arrays prohibits the
- creation of initialized memories. This effectively puts "mem2reg"
- on all memories that are written to in an "initial" block and
+- The ``nomeminit`` attribute on modules or arrays prohibits the
+ creation of initialized memories. This effectively puts ``mem2reg``
+ on all memories that are written to in an ``initial`` block and
are not ROMs.
-- The "nolatches" attribute on modules or always-blocks
+- The ``nolatches`` attribute on modules or always-blocks
prohibits the generation of logic-loops for latches. Instead
all not explicitly assigned values default to x-bits. This does
not affect clocked storage elements such as flip-flops.
-- The "nosync" attribute on registers prohibits the generation of a
+- The ``nosync`` attribute on registers prohibits the generation of a
storage element. The register itself will always have all bits set
to 'x' (undefined). The variable may only be used as blocking assigned
temporary variable within an always block. This is mostly used internally
by yosys to synthesize Verilog functions and access arrays.
-- The "onehot" attribute on wires mark them as onehot state register. This
+- The ``onehot`` attribute on wires mark them as onehot state register. This
is used for example for memory port sharing and set by the fsm_map pass.
-- The "blackbox" attribute on modules is used to mark empty stub modules
+- The ``blackbox`` attribute on modules is used to mark empty stub modules
that have the same ports as the real thing but do not contain information
on the internal configuration. This modules are only used by the synthesis
passes to identify input and output ports of cells. The Verilog backend
also does not output blackbox modules on default.
-- The "keep" attribute on cells and wires is used to mark objects that should
+- The ``keep`` attribute on cells and wires is used to mark objects that should
never be removed by the optimizer. This is used for example for cells that
have hidden connections that are not part of the netlist, such as IO pads.
- Setting the "keep" attribute on a module has the same effect as setting it
+ Setting the ``keep`` attribute on a module has the same effect as setting it
on all instances of the module.
-- The "keep_hierarchy" attribute on cells and modules keeps the "flatten"
+- The ``keep_hierarchy`` attribute on cells and modules keeps the ``flatten``
command from flattening the indicated cells and modules.
-- The "init" attribute on wires is set by the frontend when a register is
- initialized "FPGA-style" with 'reg foo = val'. It can be used during synthesis
- to add the necessary reset logic.
+- The ``init`` attribute on wires is set by the frontend when a register is
+ initialized "FPGA-style" with ``reg foo = val``. It can be used during
+ synthesis to add the necessary reset logic.
-- The "top" attribute on a module marks this module as the top of the
- design hierarchy. The "hierarchy" command sets this attribute when called
- with "-top". Other commands, such as "flatten" and various backends
+- The ``top`` attribute on a module marks this module as the top of the
+ design hierarchy. The ``hierarchy`` command sets this attribute when called
+ with ``-top``. Other commands, such as ``flatten`` and various backends
use this attribute to determine the top module.
-- The "src" attribute is set on cells and wires created by to the string
- "<hdl-file-name>:<line-number>" by the HDL front-end and is then carried
+- The ``src`` attribute is set on cells and wires created by to the string
+ ``<hdl-file-name>:<line-number>`` by the HDL front-end and is then carried
through the synthesis. When entities are combined, a new |-separated
string is created that contains all the string from the original entities.
-- In addition to the (* ... *) attribute syntax, yosys supports
- the non-standard {* ... *} attribute syntax to set default attributes
- for everything that comes after the {* ... *} statement. (Reset
- by adding an empty {* *} statement.)
+- In addition to the ``(* ... *)`` attribute syntax, yosys supports
+ the non-standard ``{* ... *}`` attribute syntax to set default attributes
+ for everything that comes after the ``{* ... *}`` statement. (Reset
+ by adding an empty ``{* *}`` statement.)
- In module parameter and port declarations, and cell port and parameter
lists, a trailing comma is ignored. This simplifies writing verilog code
generators a bit in some cases.
-- Modules can be declared with "module mod_name(...);" (with three dots
+- Modules can be declared with ``module mod_name(...);`` (with three dots
instead of a list of module ports). With this syntax it is sufficient
to simply declare a module port as 'input' or 'output' in the module
body.
@@ -326,7 +338,7 @@ Verilog Attributes and non-standard features
assign b = 42;
"""
-- The attribute "via_celltype" can be used to implement a Verilog task or
+- The attribute ``via_celltype`` can be used to implement a Verilog task or
function by instantiating the specified cell type. The value is the name
of the cell type to use. For functions the name of the output port can
be specified by appending it to the cell type separated by a whitespace.
@@ -354,9 +366,9 @@ Verilog Attributes and non-standard features
endmodule
- A limited subset of DPI-C functions is supported. The plugin mechanism
- (see "help plugin") can be used to load .so files with implementations
+ (see ``help plugin``) can be used to load .so files with implementations
of DPI-C routines. As a non-standard extension it is possible to specify
- a plugin alias using the "<alias>:" syntax. for example:
+ a plugin alias using the ``<alias>:`` syntax. For example:
module dpitest;
import "DPI-C" function foo:round = real my_round (real);
@@ -365,11 +377,11 @@ Verilog Attributes and non-standard features
$ yosys -p 'plugin -a foo -i /lib/libm.so; read_verilog dpitest.v'
-- Sized constants (the syntax <size>'s?[bodh]<value>) support constant
+- Sized constants (the syntax ``<size>'s?[bodh]<value>``) support constant
expressions as <size>. If the expression is not a simple identifier, it
- must be put in parentheses. Examples: WIDTH'd42, (4+2)'b101010
+ must be put in parentheses. Examples: ``WIDTH'd42``, ``(4+2)'b101010``
-- The system tasks $finish and $display are supported in initial blocks
+- The system tasks ``$finish`` and ``$display`` are supported in initial blocks
in an unconditional context (only if/case statements on parameters
and constant values). The intended use for this is synthesis-time DRC.
@@ -377,42 +389,63 @@ Verilog Attributes and non-standard features
Non-standard or SystemVerilog features for formal verification
==============================================================
-- Support for "assert", "assume", and "restrict" is enabled when
- read_verilog is called with -formal.
+- Support for ``assert``, ``assume``, ``restrict``, and ``cover`` is enabled
+ when ``read_verilog`` is called with ``-formal``.
-- The system task $initstate evaluates to 1 in the initial state and
+- The system task ``$initstate`` evaluates to 1 in the initial state and
to 0 otherwise.
-- The system task $anyconst evaluates to any constant value.
+- The system function ``$anyconst`` evaluates to any constant value. This is
+ equivalent to declaring a reg as ``rand const``, but also works outside
+ of checkers. (Yosys also supports ``rand const`` outside checkers.)
-- The system task $anyseq evaluates to any value, possibly a different
- value in each cycle.
+- The system function ``$anyseq`` evaluates to any value, possibly a different
+ value in each cycle. This is equivalent to declaring a reg as ``rand``,
+ but also works outside of checkers. (Yosys also supports ``rand``
+ variables outside checkers.)
-- The SystemVerilog tasks $past, $stable, $rose and $fell are supported
- in any clocked block.
+- The system functions ``$allconst`` and ``$allseq`` can be used to construct
+ formal exist-forall problems. Assumptions only hold if the trace satisfies
+ the assumtion for all ``$allconst/$allseq`` values. For assertions and cover
+ statements it is sufficient if just one ``$allconst/$allseq`` value triggers
+ the property (similar to ``$anyconst/$anyseq``).
-- The syntax @($global_clock) can be used to create FFs that have no
- explicit clock input ($ff cells).
+- Wires/registers decalred using the ``anyconst/anyseq/allconst/allseq`` attribute
+ (for example ``(* anyconst *) reg [7:0] foobar;``) will behave as if driven
+ by a ``$anyconst/$anyseq/$allconst/$allseq`` function.
+
+- The SystemVerilog tasks ``$past``, ``$stable``, ``$rose`` and ``$fell`` are
+ supported in any clocked block.
+
+- The syntax ``@($global_clock)`` can be used to create FFs that have no
+ explicit clock input ($ff cells). The same can be achieved by using
+ ``@(posedge <netname>)`` or ``@(negedge <netname>)`` when ``<netname>``
+ is marked with the ``(* gclk *)`` Verilog attribute.
Supported features from SystemVerilog
=====================================
-When read_verilog is called with -sv, it accepts some language features
+When ``read_verilog`` is called with ``-sv``, it accepts some language features
from SystemVerilog:
-- The "assert" statement from SystemVerilog is supported in its most basic
- form. In module context: "assert property (<expression>);" and within an
- always block: "assert(<expression>);". It is transformed to a $assert cell.
+- The ``assert`` statement from SystemVerilog is supported in its most basic
+ form. In module context: ``assert property (<expression>);`` and within an
+ always block: ``assert(<expression>);``. It is transformed to a $assert cell.
+
+- The ``assume``, ``restrict``, and ``cover`` statements from SystemVerilog are
+ also supported. The same limitations as with the ``assert`` statement apply.
-- The "assume" and "restrict" statements from SystemVerilog are also
- supported. The same limitations as with the "assert" statement apply.
+- The keywords ``always_comb``, ``always_ff`` and ``always_latch``, ``logic``
+ and ``bit`` are supported.
-- The keywords "always_comb", "always_ff" and "always_latch", "logic" and
- "bit" are supported.
+- Declaring free variables with ``rand`` and ``rand const`` is supported.
+
+- Checkers without a port list that do not need to be instantiated (but instead
+ behave like a named block) are supported.
- SystemVerilog packages are supported. Once a SystemVerilog file is read
- into a design with "read_verilog", all its packages are available to
+ into a design with ``read_verilog``, all its packages are available to
SystemVerilog files being read into the same design afterwards.
@@ -448,4 +481,3 @@ Notes:
- To run `make manual` you need to have installed yosys with `make install`,
otherwise it will fail on finding `kernel/yosys.h` while building
`PRESENTATION_Prog`.
-
diff --git a/backends/aiger/Makefile.inc b/backends/aiger/Makefile.inc
new file mode 100644
index 00000000..0fc37e95
--- /dev/null
+++ b/backends/aiger/Makefile.inc
@@ -0,0 +1,3 @@
+
+OBJS += backends/aiger/aiger.o
+
diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc
new file mode 100644
index 00000000..c323691a
--- /dev/null
+++ b/backends/aiger/aiger.cc
@@ -0,0 +1,754 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+void aiger_encode(std::ostream &f, int x)
+{
+ log_assert(x >= 0);
+
+ while (x & ~0x7f) {
+ f.put((x & 0x7f) | 0x80);
+ x = x >> 7;
+ }
+
+ f.put(x);
+}
+
+struct AigerWriter
+{
+ Module *module;
+ bool zinit_mode;
+ SigMap sigmap;
+
+ dict<SigBit, bool> init_map;
+ pool<SigBit> input_bits, output_bits;
+ dict<SigBit, SigBit> not_map, ff_map, alias_map;
+ dict<SigBit, pair<SigBit, SigBit>> and_map;
+ vector<pair<SigBit, SigBit>> asserts, assumes;
+ vector<pair<SigBit, SigBit>> liveness, fairness;
+ pool<SigBit> initstate_bits;
+
+ vector<pair<int, int>> aig_gates;
+ vector<int> aig_latchin, aig_latchinit, aig_outputs;
+ int aig_m = 0, aig_i = 0, aig_l = 0, aig_o = 0, aig_a = 0;
+ int aig_b = 0, aig_c = 0, aig_j = 0, aig_f = 0;
+
+ dict<SigBit, int> aig_map;
+ dict<SigBit, int> ordered_outputs;
+ dict<SigBit, int> ordered_latches;
+
+ dict<SigBit, int> init_inputs;
+ int initstate_ff = 0;
+
+ int mkgate(int a0, int a1)
+ {
+ aig_m++, aig_a++;
+ aig_gates.push_back(a0 > a1 ? make_pair(a0, a1) : make_pair(a1, a0));
+ return 2*aig_m;
+ }
+
+ int bit2aig(SigBit bit)
+ {
+ if (aig_map.count(bit) == 0)
+ {
+ aig_map[bit] = -1;
+
+ if (initstate_bits.count(bit)) {
+ log_assert(initstate_ff > 0);
+ aig_map[bit] = initstate_ff;
+ } else
+ if (not_map.count(bit)) {
+ int a = bit2aig(not_map.at(bit)) ^ 1;
+ aig_map[bit] = a;
+ } else
+ if (and_map.count(bit)) {
+ auto args = and_map.at(bit);
+ int a0 = bit2aig(args.first);
+ int a1 = bit2aig(args.second);
+ aig_map[bit] = mkgate(a0, a1);
+ } else
+ if (alias_map.count(bit)) {
+ aig_map[bit] = bit2aig(alias_map.at(bit));
+ }
+
+ if (bit == State::Sx || bit == State::Sz)
+ log_error("Design contains 'x' or 'z' bits. Use 'setundef' to replace those constants.\n");
+ }
+
+ log_assert(aig_map.at(bit) >= 0);
+ return aig_map.at(bit);
+ }
+
+ AigerWriter(Module *module, bool zinit_mode) : module(module), zinit_mode(zinit_mode), sigmap(module)
+ {
+ pool<SigBit> undriven_bits;
+ pool<SigBit> unused_bits;
+
+ // promote public wires
+ for (auto wire : module->wires())
+ if (wire->name[0] == '\\')
+ sigmap.add(wire);
+
+ // promote input wires
+ for (auto wire : module->wires())
+ if (wire->port_input)
+ sigmap.add(wire);
+
+ // promote output wires
+ for (auto wire : module->wires())
+ if (wire->port_output)
+ sigmap.add(wire);
+
+ for (auto wire : module->wires())
+ {
+ if (wire->attributes.count("\\init")) {
+ SigSpec initsig = sigmap(wire);
+ Const initval = wire->attributes.at("\\init");
+ for (int i = 0; i < GetSize(wire) && i < GetSize(initval); i++)
+ if (initval[i] == State::S0 || initval[i] == State::S1)
+ init_map[initsig[i]] = initval[i] == State::S1;
+ }
+
+ for (int i = 0; i < GetSize(wire); i++)
+ {
+ SigBit wirebit(wire, i);
+ SigBit bit = sigmap(wirebit);
+
+ if (bit.wire == nullptr) {
+ if (wire->port_output) {
+ aig_map[wirebit] = (bit == State::S1) ? 1 : 0;
+ output_bits.insert(wirebit);
+ }
+ continue;
+ }
+
+ undriven_bits.insert(bit);
+ unused_bits.insert(bit);
+
+ if (wire->port_input)
+ input_bits.insert(bit);
+
+ if (wire->port_output) {
+ if (bit != wirebit)
+ alias_map[wirebit] = bit;
+ output_bits.insert(wirebit);
+ }
+ }
+ }
+
+ for (auto bit : input_bits)
+ undriven_bits.erase(bit);
+
+ for (auto bit : output_bits)
+ unused_bits.erase(bit);
+
+ for (auto cell : module->cells())
+ {
+ if (cell->type == "$_NOT_")
+ {
+ SigBit A = sigmap(cell->getPort("\\A").as_bit());
+ SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
+ unused_bits.erase(A);
+ undriven_bits.erase(Y);
+ not_map[Y] = A;
+ continue;
+ }
+
+ if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_"))
+ {
+ SigBit D = sigmap(cell->getPort("\\D").as_bit());
+ SigBit Q = sigmap(cell->getPort("\\Q").as_bit());
+ unused_bits.erase(D);
+ undriven_bits.erase(Q);
+ ff_map[Q] = D;
+ continue;
+ }
+
+ if (cell->type == "$_AND_")
+ {
+ SigBit A = sigmap(cell->getPort("\\A").as_bit());
+ SigBit B = sigmap(cell->getPort("\\B").as_bit());
+ SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
+ unused_bits.erase(A);
+ unused_bits.erase(B);
+ undriven_bits.erase(Y);
+ and_map[Y] = make_pair(A, B);
+ continue;
+ }
+
+ if (cell->type == "$initstate")
+ {
+ SigBit Y = sigmap(cell->getPort("\\Y").as_bit());
+ undriven_bits.erase(Y);
+ initstate_bits.insert(Y);
+ continue;
+ }
+
+ if (cell->type == "$assert")
+ {
+ SigBit A = sigmap(cell->getPort("\\A").as_bit());
+ SigBit EN = sigmap(cell->getPort("\\EN").as_bit());
+ unused_bits.erase(A);
+ unused_bits.erase(EN);
+ asserts.push_back(make_pair(A, EN));
+ continue;
+ }
+
+ if (cell->type == "$assume")
+ {
+ SigBit A = sigmap(cell->getPort("\\A").as_bit());
+ SigBit EN = sigmap(cell->getPort("\\EN").as_bit());
+ unused_bits.erase(A);
+ unused_bits.erase(EN);
+ assumes.push_back(make_pair(A, EN));
+ continue;
+ }
+
+ if (cell->type == "$live")
+ {
+ SigBit A = sigmap(cell->getPort("\\A").as_bit());
+ SigBit EN = sigmap(cell->getPort("\\EN").as_bit());
+ unused_bits.erase(A);
+ unused_bits.erase(EN);
+ liveness.push_back(make_pair(A, EN));
+ continue;
+ }
+
+ if (cell->type == "$fair")
+ {
+ SigBit A = sigmap(cell->getPort("\\A").as_bit());
+ SigBit EN = sigmap(cell->getPort("\\EN").as_bit());
+ unused_bits.erase(A);
+ unused_bits.erase(EN);
+ fairness.push_back(make_pair(A, EN));
+ continue;
+ }
+
+ if (cell->type == "$anyconst")
+ {
+ for (auto bit : sigmap(cell->getPort("\\Y"))) {
+ undriven_bits.erase(bit);
+ ff_map[bit] = bit;
+ }
+ continue;
+ }
+
+ if (cell->type == "$anyseq")
+ {
+ for (auto bit : sigmap(cell->getPort("\\Y"))) {
+ undriven_bits.erase(bit);
+ input_bits.insert(bit);
+ }
+ continue;
+ }
+
+ log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
+ }
+
+ for (auto bit : unused_bits)
+ undriven_bits.erase(bit);
+
+ if (!undriven_bits.empty()) {
+ undriven_bits.sort();
+ for (auto bit : undriven_bits) {
+ log_warning("Treating undriven bit %s.%s like $anyseq.\n", log_id(module), log_signal(bit));
+ input_bits.insert(bit);
+ }
+ log_warning("Treating a total of %d undriven bits in %s like $anyseq.\n", GetSize(undriven_bits), log_id(module));
+ }
+
+ init_map.sort();
+ input_bits.sort();
+ output_bits.sort();
+ not_map.sort();
+ ff_map.sort();
+ and_map.sort();
+
+ aig_map[State::S0] = 0;
+ aig_map[State::S1] = 1;
+
+ for (auto bit : input_bits) {
+ aig_m++, aig_i++;
+ aig_map[bit] = 2*aig_m;
+ }
+
+ if (zinit_mode)
+ {
+ for (auto it : ff_map) {
+ if (init_map.count(it.first))
+ continue;
+ aig_m++, aig_i++;
+ init_inputs[it.first] = 2*aig_m;
+ }
+ }
+
+ int fair_live_inputs_cnt = GetSize(liveness);
+ int fair_live_inputs_m = aig_m;
+
+ aig_m += fair_live_inputs_cnt;
+ aig_i += fair_live_inputs_cnt;
+
+ for (auto it : ff_map) {
+ aig_m++, aig_l++;
+ aig_map[it.first] = 2*aig_m;
+ ordered_latches[it.first] = aig_l-1;
+ if (init_map.count(it.first) == 0)
+ aig_latchinit.push_back(2);
+ else
+ aig_latchinit.push_back(init_map.at(it.first) ? 1 : 0);
+ }
+
+ if (!initstate_bits.empty() || !init_inputs.empty()) {
+ aig_m++, aig_l++;
+ initstate_ff = 2*aig_m+1;
+ aig_latchinit.push_back(0);
+ }
+
+ int fair_live_latches_cnt = GetSize(fairness) + 2*GetSize(liveness);
+ int fair_live_latches_m = aig_m;
+ int fair_live_latches_l = aig_l;
+
+ aig_m += fair_live_latches_cnt;
+ aig_l += fair_live_latches_cnt;
+
+ for (int i = 0; i < fair_live_latches_cnt; i++)
+ aig_latchinit.push_back(0);
+
+ if (zinit_mode)
+ {
+ for (auto it : ff_map)
+ {
+ int l = ordered_latches[it.first];
+
+ if (aig_latchinit.at(l) == 1)
+ aig_map[it.first] ^= 1;
+
+ if (aig_latchinit.at(l) == 2)
+ {
+ int gated_ffout = mkgate(aig_map[it.first], initstate_ff^1);
+ int gated_initin = mkgate(init_inputs[it.first], initstate_ff);
+ aig_map[it.first] = mkgate(gated_ffout^1, gated_initin^1)^1;
+ }
+ }
+ }
+
+ for (auto it : ff_map) {
+ int a = bit2aig(it.second);
+ int l = ordered_latches[it.first];
+ if (zinit_mode && aig_latchinit.at(l) == 1)
+ aig_latchin.push_back(a ^ 1);
+ else
+ aig_latchin.push_back(a);
+ }
+
+ if (!initstate_bits.empty() || !init_inputs.empty())
+ aig_latchin.push_back(1);
+
+ for (auto bit : output_bits) {
+ aig_o++;
+ ordered_outputs[bit] = aig_o-1;
+ aig_outputs.push_back(bit2aig(bit));
+ }
+
+ for (auto it : asserts) {
+ aig_b++;
+ int bit_a = bit2aig(it.first);
+ int bit_en = bit2aig(it.second);
+ aig_outputs.push_back(mkgate(bit_a^1, bit_en));
+ }
+
+ for (auto it : assumes) {
+ aig_c++;
+ int bit_a = bit2aig(it.first);
+ int bit_en = bit2aig(it.second);
+ aig_outputs.push_back(mkgate(bit_a^1, bit_en)^1);
+ }
+
+ for (auto it : liveness)
+ {
+ int input_m = ++fair_live_inputs_m;
+ int latch_m1 = ++fair_live_latches_m;
+ int latch_m2 = ++fair_live_latches_m;
+
+ log_assert(GetSize(aig_latchin) == fair_live_latches_l);
+ fair_live_latches_l += 2;
+
+ int bit_a = bit2aig(it.first);
+ int bit_en = bit2aig(it.second);
+ int bit_s = 2*input_m;
+ int bit_q1 = 2*latch_m1;
+ int bit_q2 = 2*latch_m2;
+
+ int bit_d1 = mkgate(mkgate(bit_s, bit_en)^1, bit_q1^1)^1;
+ int bit_d2 = mkgate(mkgate(bit_d1, bit_a)^1, bit_q2^1)^1;
+
+ aig_j++;
+ aig_latchin.push_back(bit_d1);
+ aig_latchin.push_back(bit_d2);
+ aig_outputs.push_back(mkgate(bit_q1, bit_q2^1));
+ }
+
+ for (auto it : fairness)
+ {
+ int latch_m = ++fair_live_latches_m;
+
+ log_assert(GetSize(aig_latchin) == fair_live_latches_l);
+ fair_live_latches_l += 1;
+
+ int bit_a = bit2aig(it.first);
+ int bit_en = bit2aig(it.second);
+ int bit_q = 2*latch_m;
+
+ aig_f++;
+ aig_latchin.push_back(mkgate(mkgate(bit_q^1, bit_en^1)^1, bit_a^1));
+ aig_outputs.push_back(bit_q^1);
+ }
+ }
+
+ void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode)
+ {
+ int aig_obc = aig_o + aig_b + aig_c;
+ int aig_obcj = aig_obc + aig_j;
+ int aig_obcjf = aig_obcj + aig_f;
+
+ log_assert(aig_m == aig_i + aig_l + aig_a);
+ log_assert(aig_l == GetSize(aig_latchin));
+ log_assert(aig_l == GetSize(aig_latchinit));
+ log_assert(aig_obcjf == GetSize(aig_outputs));
+
+ if (miter_mode) {
+ if (aig_b || aig_c || aig_j || aig_f)
+ log_error("Running AIGER back-end in -miter mode, but design contains $assert, $assume, $live and/or $fair cells!\n");
+ f << stringf("%s %d %d %d 0 %d %d\n", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_a, aig_o);
+ } else {
+ f << stringf("%s %d %d %d %d %d", ascii_mode ? "aag" : "aig", aig_m, aig_i, aig_l, aig_o, aig_a);
+ if (aig_b || aig_c || aig_j || aig_f)
+ f << stringf(" %d %d %d %d", aig_b, aig_c, aig_j, aig_f);
+ f << stringf("\n");
+ }
+
+ if (ascii_mode)
+ {
+ for (int i = 0; i < aig_i; i++)
+ f << stringf("%d\n", 2*i+2);
+
+ for (int i = 0; i < aig_l; i++) {
+ if (zinit_mode || aig_latchinit.at(i) == 0)
+ f << stringf("%d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i));
+ else if (aig_latchinit.at(i) == 1)
+ f << stringf("%d %d 1\n", 2*(aig_i+i)+2, aig_latchin.at(i));
+ else if (aig_latchinit.at(i) == 2)
+ f << stringf("%d %d %d\n", 2*(aig_i+i)+2, aig_latchin.at(i), 2*(aig_i+i)+2);
+ }
+
+ for (int i = 0; i < aig_obc; i++)
+ f << stringf("%d\n", aig_outputs.at(i));
+
+ for (int i = aig_obc; i < aig_obcj; i++)
+ f << stringf("1\n");
+
+ for (int i = aig_obc; i < aig_obcj; i++)
+ f << stringf("%d\n", aig_outputs.at(i));
+
+ for (int i = aig_obcj; i < aig_obcjf; i++)
+ f << stringf("%d\n", aig_outputs.at(i));
+
+ for (int i = 0; i < aig_a; i++)
+ f << stringf("%d %d %d\n", 2*(aig_i+aig_l+i)+2, aig_gates.at(i).first, aig_gates.at(i).second);
+ }
+ else
+ {
+ for (int i = 0; i < aig_l; i++) {
+ if (zinit_mode || aig_latchinit.at(i) == 0)
+ f << stringf("%d\n", aig_latchin.at(i));
+ else if (aig_latchinit.at(i) == 1)
+ f << stringf("%d 1\n", aig_latchin.at(i));
+ else if (aig_latchinit.at(i) == 2)
+ f << stringf("%d %d\n", aig_latchin.at(i), 2*(aig_i+i)+2);
+ }
+
+ for (int i = 0; i < aig_obc; i++)
+ f << stringf("%d\n", aig_outputs.at(i));
+
+ for (int i = aig_obc; i < aig_obcj; i++)
+ f << stringf("1\n");
+
+ for (int i = aig_obc; i < aig_obcj; i++)
+ f << stringf("%d\n", aig_outputs.at(i));
+
+ for (int i = aig_obcj; i < aig_obcjf; i++)
+ f << stringf("%d\n", aig_outputs.at(i));
+
+ for (int i = 0; i < aig_a; i++) {
+ int lhs = 2*(aig_i+aig_l+i)+2;
+ int rhs0 = aig_gates.at(i).first;
+ int rhs1 = aig_gates.at(i).second;
+ int delta0 = lhs - rhs0;
+ int delta1 = rhs0 - rhs1;
+ aiger_encode(f, delta0);
+ aiger_encode(f, delta1);
+ }
+ }
+
+ if (symbols_mode)
+ {
+ dict<string, vector<string>> symbols;
+
+ for (auto wire : module->wires())
+ {
+ if (wire->name[0] == '$')
+ continue;
+
+ SigSpec sig = sigmap(wire);
+
+ for (int i = 0; i < GetSize(wire); i++)
+ {
+ if (sig[i].wire == nullptr) {
+ if (wire->port_output)
+ sig[i] = SigBit(wire, i);
+ else
+ continue;
+ }
+
+ if (wire->port_input) {
+ int a = aig_map.at(sig[i]);
+ log_assert((a & 1) == 0);
+ if (GetSize(wire) != 1)
+ symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", log_id(wire), i));
+ else
+ symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire)));
+ }
+
+ if (wire->port_output) {
+ int o = ordered_outputs.at(SigSpec(wire, i));
+ if (GetSize(wire) != 1)
+ symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i));
+ else
+ symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire)));
+ }
+
+ if (init_inputs.count(sig[i])) {
+ int a = init_inputs.at(sig[i]);
+ log_assert((a & 1) == 0);
+ if (GetSize(wire) != 1)
+ symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i));
+ else
+ symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire)));
+ }
+
+ if (ordered_latches.count(sig[i])) {
+ int l = ordered_latches.at(sig[i]);
+ const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : "";
+ if (GetSize(wire) != 1)
+ symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, log_id(wire), i));
+ else
+ symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, log_id(wire)));
+ }
+ }
+ }
+
+ symbols.sort();
+
+ for (auto &sym : symbols) {
+ f << sym.first;
+ std::sort(sym.second.begin(), sym.second.end());
+ for (auto &s : sym.second)
+ f << " " << s;
+ f << std::endl;
+ }
+ }
+
+ f << stringf("c\nGenerated by %s\n", yosys_version_str);
+ }
+
+ void write_map(std::ostream &f, bool verbose_map)
+ {
+ dict<int, string> input_lines;
+ dict<int, string> init_lines;
+ dict<int, string> output_lines;
+ dict<int, string> latch_lines;
+ dict<int, string> wire_lines;
+
+ for (auto wire : module->wires())
+ {
+ if (!verbose_map && wire->name[0] == '$')
+ continue;
+
+ SigSpec sig = sigmap(wire);
+
+ for (int i = 0; i < GetSize(wire); i++)
+ {
+ if (aig_map.count(sig[i]) == 0 || sig[i].wire == nullptr)
+ continue;
+
+ int a = aig_map.at(sig[i]);
+
+ if (verbose_map)
+ wire_lines[a] += stringf("wire %d %d %s\n", a, i, log_id(wire));
+
+ if (wire->port_input) {
+ log_assert((a & 1) == 0);
+ input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire));
+ }
+
+ if (wire->port_output) {
+ int o = ordered_outputs.at(sig[i]);
+ output_lines[o] += stringf("output %d %d %s\n", o, i, log_id(wire));
+ }
+
+ if (init_inputs.count(sig[i])) {
+ int a = init_inputs.at(sig[i]);
+ log_assert((a & 1) == 0);
+ init_lines[a] += stringf("init %d %d %s\n", (a >> 1)-1, i, log_id(wire));
+ }
+
+ if (ordered_latches.count(sig[i])) {
+ int l = ordered_latches.at(sig[i]);
+ if (zinit_mode && (aig_latchinit.at(l) == 1))
+ latch_lines[l] += stringf("invlatch %d %d %s\n", l, i, log_id(wire));
+ else
+ latch_lines[l] += stringf("latch %d %d %s\n", l, i, log_id(wire));
+ }
+ }
+ }
+
+ input_lines.sort();
+ for (auto &it : input_lines)
+ f << it.second;
+
+ init_lines.sort();
+ for (auto &it : init_lines)
+ f << it.second;
+
+ output_lines.sort();
+ for (auto &it : output_lines)
+ f << it.second;
+
+ latch_lines.sort();
+ for (auto &it : latch_lines)
+ f << it.second;
+
+ wire_lines.sort();
+ for (auto &it : wire_lines)
+ f << it.second;
+ }
+};
+
+struct AigerBackend : public Backend {
+ AigerBackend() : Backend("aiger", "write design to AIGER file") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" write_aiger [options] [filename]\n");
+ log("\n");
+ log("Write the current design to an AIGER file. The design must be flattened and\n");
+ log("must not contain any cell types except $_AND_, $_NOT_, simple FF types,\n");
+ log("$assert and $assume cells, and $initstate cells.\n");
+ log("\n");
+ log("$assert and $assume cells are converted to AIGER bad state properties and\n");
+ log("invariant constraints.\n");
+ log("\n");
+ log(" -ascii\n");
+ log(" write ASCII version of AGIER format\n");
+ log("\n");
+ log(" -zinit\n");
+ log(" convert FFs to zero-initialized FFs, adding additional inputs for\n");
+ log(" uninitialized FFs.\n");
+ log("\n");
+ log(" -miter\n");
+ log(" design outputs are AIGER bad state properties\n");
+ log("\n");
+ log(" -symbols\n");
+ log(" include a symbol table in the generated AIGER file\n");
+ log("\n");
+ log(" -map <filename>\n");
+ log(" write an extra file with port and latch symbols\n");
+ log("\n");
+ log(" -vmap <filename>\n");
+ log(" like -map, but more verbose\n");
+ log("\n");
+ }
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ bool ascii_mode = false;
+ bool zinit_mode = false;
+ bool miter_mode = false;
+ bool symbols_mode = false;
+ bool verbose_map = false;
+ std::string map_filename;
+
+ log_header(design, "Executing AIGER backend.\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-ascii") {
+ ascii_mode = true;
+ continue;
+ }
+ if (args[argidx] == "-zinit") {
+ zinit_mode = true;
+ continue;
+ }
+ if (args[argidx] == "-miter") {
+ miter_mode = true;
+ continue;
+ }
+ if (args[argidx] == "-symbols") {
+ symbols_mode = true;
+ continue;
+ }
+ if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) {
+ map_filename = args[++argidx];
+ continue;
+ }
+ if (map_filename.empty() && args[argidx] == "-vmap" && argidx+1 < args.size()) {
+ map_filename = args[++argidx];
+ verbose_map = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(f, filename, args, argidx);
+
+ Module *top_module = design->top_module();
+
+ if (top_module == nullptr)
+ log_error("Can't find top module in current design!\n");
+
+ AigerWriter writer(top_module, zinit_mode);
+ writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode);
+
+ if (!map_filename.empty()) {
+ std::ofstream mapf;
+ mapf.open(map_filename.c_str(), std::ofstream::trunc);
+ if (mapf.fail())
+ log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno));
+ writer.write_map(mapf, verbose_map);
+ }
+ }
+} AigerBackend;
+
+PRIVATE_NAMESPACE_END
diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc
index d9d0cc17..0db5ff27 100644
--- a/backends/blif/blif.cc
+++ b/backends/blif/blif.cc
@@ -38,8 +38,10 @@ struct BlifDumperConfig
bool impltf_mode;
bool gates_mode;
bool cname_mode;
+ bool iname_mode;
bool param_mode;
bool attr_mode;
+ bool iattr_mode;
bool blackbox_mode;
bool noalias_mode;
@@ -48,7 +50,8 @@ struct BlifDumperConfig
std::string true_type, true_out, false_type, false_out, undef_type, undef_out;
BlifDumperConfig() : icells_mode(false), conn_mode(false), impltf_mode(false), gates_mode(false),
- cname_mode(false), param_mode(false), attr_mode(false), blackbox_mode(false), noalias_mode(false) { }
+ cname_mode(false), iname_mode(false), param_mode(false), attr_mode(false), iattr_mode(false),
+ blackbox_mode(false), noalias_mode(false) { }
};
struct BlifDumper
@@ -112,7 +115,7 @@ struct BlifDumper
str[i] = '?';
if (sig.wire->width != 1)
- str += stringf("[%d]", sig.offset);
+ str += stringf("[%d]", sig.wire->upto ? sig.wire->start_offset+sig.wire->width-sig.offset-1 : sig.wire->start_offset+sig.offset);
cstr_buf.push_back(str);
return cstr_buf.back().c_str();
@@ -240,106 +243,118 @@ struct BlifDumper
if (!config->icells_mode && cell->type == "$_NOT_") {
f << stringf(".names %s %s\n0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_AND_") {
f << stringf(".names %s %s %s\n11 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_OR_") {
f << stringf(".names %s %s %s\n1- 1\n-1 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_XOR_") {
f << stringf(".names %s %s %s\n10 1\n01 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_NAND_") {
f << stringf(".names %s %s %s\n0- 1\n-0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_NOR_") {
f << stringf(".names %s %s %s\n00 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_XNOR_") {
f << stringf(".names %s %s %s\n11 1\n00 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
+ }
+
+ if (!config->icells_mode && cell->type == "$_ANDNOT_") {
+ f << stringf(".names %s %s %s\n10 1\n",
+ cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
+ goto internal_cell;
+ }
+
+ if (!config->icells_mode && cell->type == "$_ORNOT_") {
+ f << stringf(".names %s %s %s\n1- 1\n-0 1\n",
+ cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y")));
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_AOI3_") {
f << stringf(".names %s %s %s %s\n-00 1\n0-0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\C")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_OAI3_") {
f << stringf(".names %s %s %s %s\n00- 1\n--0 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\C")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_AOI4_") {
f << stringf(".names %s %s %s %s %s\n-0-0 1\n-00- 1\n0--0 1\n0-0- 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")),
cstr(cell->getPort("\\C")), cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_OAI4_") {
f << stringf(".names %s %s %s %s %s\n00-- 1\n--00 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")),
cstr(cell->getPort("\\C")), cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_MUX_") {
f << stringf(".names %s %s %s %s\n1-0 1\n-11 1\n",
cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")),
cstr(cell->getPort("\\S")), cstr(cell->getPort("\\Y")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_FF_") {
f << stringf(".latch %s %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr_init(cell->getPort("\\Q")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_DFF_N_") {
f << stringf(".latch %s %s fe %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr(cell->getPort("\\C")), cstr_init(cell->getPort("\\Q")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_DFF_P_") {
f << stringf(".latch %s %s re %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr(cell->getPort("\\C")), cstr_init(cell->getPort("\\Q")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_DLATCH_N_") {
f << stringf(".latch %s %s al %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr(cell->getPort("\\E")), cstr_init(cell->getPort("\\Q")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$_DLATCH_P_") {
f << stringf(".latch %s %s ah %s%s\n", cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")),
cstr(cell->getPort("\\E")), cstr_init(cell->getPort("\\Q")));
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$lut") {
@@ -361,7 +376,7 @@ struct BlifDumper
}
f << " 1\n";
}
- continue;
+ goto internal_cell;
}
if (!config->icells_mode && cell->type == "$sop") {
@@ -389,7 +404,7 @@ struct BlifDumper
}
f << " 1\n";
}
- continue;
+ goto internal_cell;
}
f << stringf(".%s %s", subckt_or_gate(cell->type.str()), cstr(cell->type));
@@ -409,6 +424,14 @@ struct BlifDumper
dump_params(".attr", cell->attributes);
if (config->param_mode)
dump_params(".param", cell->parameters);
+
+ if (0) {
+ internal_cell:
+ if (config->iname_mode)
+ f << stringf(".cname %s\n", cstr(cell->name));
+ if (config->iattr_mode)
+ dump_params(".attr", cell->attributes);
+ }
}
for (auto &conn : module->connections())
@@ -441,7 +464,7 @@ struct BlifDumper
struct BlifBackend : public Backend {
BlifBackend() : Backend("blif", "write design to BLIF file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -499,6 +522,11 @@ struct BlifBackend : public Backend {
log(" -cname\n");
log(" use the non-standard .cname statement to write cell names\n");
log("\n");
+ log(" -iname, -iattr\n");
+ log(" enable -cname and -attr functionality for .names statements\n");
+ log(" (the .cname and .attr statements will be included in the BLIF\n");
+ log(" output after the truth table for the .names statement)\n");
+ log("\n");
log(" -blackbox\n");
log(" write blackbox cells with .blackbox statement.\n");
log("\n");
@@ -506,7 +534,7 @@ struct BlifBackend : public Backend {
log(" do not write definitions for the $true, $false and $undef wires.\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string top_module_name;
std::string buf_type, buf_in, buf_out;
@@ -575,6 +603,14 @@ struct BlifBackend : public Backend {
config.attr_mode = true;
continue;
}
+ if (args[argidx] == "-iname") {
+ config.iname_mode = true;
+ continue;
+ }
+ if (args[argidx] == "-iattr") {
+ config.iattr_mode = true;
+ continue;
+ }
if (args[argidx] == "-blackbox") {
config.blackbox_mode = true;
continue;
diff --git a/backends/btor/README b/backends/btor/README
deleted file mode 100644
index efcf0d8f..00000000
--- a/backends/btor/README
+++ /dev/null
@@ -1,23 +0,0 @@
-
-This is the Yosys BTOR backend.
-It is developed by Ahmed Irfan <irfan@fbk.eu> - Fondazione Bruno Kessler, Trento, Italy
-
-Master git repository for the BTOR backend:
-https://github.com/ahmedirfan1983/yosys
-
-
-[[CITE]] BTOR: Bit-Precise Modelling of Word-Level Problems for Model Checking
-Johannes Kepler University, Linz, Austria
-http://fmv.jku.at/papers/BrummayerBiereLonsing-BPR08.pdf
-
-
-Todos:
-------
-
-- Add checks for unsupported stuff
- - unsupported cell types
- - async resets
- - etc..
-
-- Add support for $lut cells
-
diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc
index bbe90e85..58d2a862 100644
--- a/backends/btor/btor.cc
+++ b/backends/btor/btor.cc
@@ -2,7 +2,6 @@
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * Copyright (C) 2014 Ahmed Irfan <irfan@fbk.eu>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -18,1093 +17,1112 @@
*
*/
-// [[CITE]] BTOR: Bit-Precise Modelling of Word-Level Problems for Model Checking
-// Johannes Kepler University, Linz, Austria
-// http://fmv.jku.at/papers/BrummayerBiereLonsing-BPR08.pdf
-
#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/log.h"
#include <string>
-#include <math.h>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-struct BtorDumperConfig
+struct BtorWorker
{
- bool subckt_mode;
- bool conn_mode;
- bool impltf_mode;
+ std::ostream &f;
+ SigMap sigmap;
+ RTLIL::Module *module;
+ bool verbose;
+ bool single_bad;
- std::string buf_type, buf_in, buf_out;
- std::string true_type, true_out, false_type, false_out;
+ int next_nid = 1;
+ int initstate_nid = -1;
- BtorDumperConfig() : subckt_mode(false), conn_mode(false), impltf_mode(false) { }
-};
+ // <width> => <sid>
+ dict<int, int> sorts_bv;
-struct WireInfo
-{
- RTLIL::IdString cell_name;
- const RTLIL::SigChunk *chunk;
+ // (<address-width>, <data-width>) => <sid>
+ dict<pair<int, int>, int> sorts_mem;
- WireInfo(RTLIL::IdString c, const RTLIL::SigChunk* ch) : cell_name(c), chunk(ch) { }
-};
+ // SigBit => (<nid>, <bitidx>)
+ dict<SigBit, pair<int, int>> bit_nid;
-struct WireInfoOrder
-{
- bool operator() (const WireInfo& x, const WireInfo& y)
+ // <nid> => <bvwidth>
+ dict<int, int> nid_width;
+
+ // SigSpec => <nid>
+ dict<SigSpec, int> sig_nid;
+
+ // bit to driving cell
+ dict<SigBit, Cell*> bit_cell;
+
+ // nids for constants
+ dict<Const, int> consts;
+
+ // ff inputs that need to be evaluated (<nid>, <ff_cell>)
+ vector<pair<int, Cell*>> ff_todo;
+
+ pool<Cell*> cell_recursion_guard;
+ vector<int> bad_properties;
+ dict<SigBit, bool> initbits;
+ pool<Wire*> statewires;
+ string indent;
+
+ void btorf(const char *fmt, ...)
{
- return x.chunk < y.chunk;
+ va_list ap;
+ va_start(ap, fmt);
+ f << indent << vstringf(fmt, ap);
+ va_end(ap);
}
-};
-struct BtorDumper
-{
- std::ostream &f;
- RTLIL::Module *module;
- RTLIL::Design *design;
- BtorDumperConfig *config;
- CellTypes ct;
+ void btorf_push(const string &id)
+ {
+ if (verbose) {
+ f << indent << stringf(" ; begin %s\n", id.c_str());
+ indent += " ";
+ }
+ }
- SigMap sigmap;
- std::map<RTLIL::IdString, std::set<WireInfo,WireInfoOrder>> inter_wire_map;//<wire, dependency list> for mapping the intermediate wires that are output of some cell
- std::map<RTLIL::IdString, int> line_ref;//mapping of ids to line_num of the btor file
- std::map<RTLIL::SigSpec, int> sig_ref;//mapping of sigspec to the line_num of the btor file
- int line_num;//last line number of btor file
- std::string str;//temp string for writing file
- std::map<RTLIL::IdString, bool> basic_wires;//input wires and registers
- RTLIL::IdString curr_cell; //current cell being dumped
- std::map<std::string, std::string> cell_type_translation, s_cell_type_translation; //RTLIL to BTOR translation
- std::map<int, std::set<std::pair<int,int>>> mem_next; // memory (line_number)'s set of condition and write
- BtorDumper(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, BtorDumperConfig *config) :
- f(f), module(module), design(design), config(config), ct(design), sigmap(module)
+ void btorf_pop(const string &id)
{
- line_num=0;
- str.clear();
- for(auto it=module->wires_.begin(); it!=module->wires_.end(); ++it)
- {
- if(it->second->port_input)
- {
- basic_wires[it->first]=true;
- }
- else
- {
- basic_wires[it->first]=false;
- }
- inter_wire_map[it->first].clear();
+ if (verbose) {
+ indent = indent.substr(4);
+ f << indent << stringf(" ; end %s\n", id.c_str());
}
- curr_cell.clear();
- //assert
- cell_type_translation["$assert"] = "root";
- //unary
- cell_type_translation["$not"] = "not";
- cell_type_translation["$neg"] = "neg";
- cell_type_translation["$reduce_and"] = "redand";
- cell_type_translation["$reduce_or"] = "redor";
- cell_type_translation["$reduce_xor"] = "redxor";
- cell_type_translation["$reduce_bool"] = "redor";
- //binary
- cell_type_translation["$and"] = "and";
- cell_type_translation["$or"] = "or";
- cell_type_translation["$xor"] = "xor";
- cell_type_translation["$xnor"] = "xnor";
- cell_type_translation["$shr"] = "srl";
- cell_type_translation["$shl"] = "sll";
- cell_type_translation["$sshr"] = "sra";
- cell_type_translation["$sshl"] = "sll";
- cell_type_translation["$shift"] = "srl";
- cell_type_translation["$shiftx"] = "srl";
- cell_type_translation["$lt"] = "ult";
- cell_type_translation["$le"] = "ulte";
- cell_type_translation["$gt"] = "ugt";
- cell_type_translation["$ge"] = "ugte";
- cell_type_translation["$eq"] = "eq";
- cell_type_translation["$eqx"] = "eq";
- cell_type_translation["$ne"] = "ne";
- cell_type_translation["$nex"] = "ne";
- cell_type_translation["$add"] = "add";
- cell_type_translation["$sub"] = "sub";
- cell_type_translation["$mul"] = "mul";
- cell_type_translation["$mod"] = "urem";
- cell_type_translation["$div"] = "udiv";
- //mux
- cell_type_translation["$mux"] = "cond";
- //reg
- cell_type_translation["$dff"] = "next";
- cell_type_translation["$adff"] = "next";
- cell_type_translation["$dffsr"] = "next";
- //memories
- //nothing here
- //slice
- cell_type_translation["$slice"] = "slice";
- //concat
- cell_type_translation["$concat"] = "concat";
-
- //signed cell type translation
- //binary
- s_cell_type_translation["$modx"] = "srem";
- s_cell_type_translation["$mody"] = "smod";
- s_cell_type_translation["$div"] = "sdiv";
- s_cell_type_translation["$lt"] = "slt";
- s_cell_type_translation["$le"] = "slte";
- s_cell_type_translation["$gt"] = "sgt";
- s_cell_type_translation["$ge"] = "sgte";
+ }
+ int get_bv_sid(int width)
+ {
+ if (sorts_bv.count(width) == 0) {
+ int nid = next_nid++;
+ btorf("%d sort bitvec %d\n", nid, width);
+ sorts_bv[width] = nid;
+ }
+ return sorts_bv.at(width);
}
- vector<shared_str> cstr_buf;
+ int get_mem_sid(int abits, int dbits)
+ {
+ pair<int, int> key(abits, dbits);
+ if (sorts_mem.count(key) == 0) {
+ int addr_sid = get_bv_sid(abits);
+ int data_sid = get_bv_sid(dbits);
+ int nid = next_nid++;
+ btorf("%d sort array %d %d\n", nid, addr_sid, data_sid);
+ sorts_mem[key] = nid;
+ }
+ return sorts_mem.at(key);
+ }
- const char *cstr(const RTLIL::IdString id)
+ void add_nid_sig(int nid, const SigSpec &sig)
{
- str = RTLIL::unescape_id(id);
- for (size_t i = 0; i < str.size(); ++i)
- if (str[i] == '#' || str[i] == '=')
- str[i] = '?';
- cstr_buf.push_back(str);
- return cstr_buf.back().c_str();
+ if (verbose)
+ f << indent << stringf("; %d %s\n", nid, log_signal(sig));
+
+ for (int i = 0; i < GetSize(sig); i++)
+ bit_nid[sig[i]] = make_pair(nid, i);
+
+ sig_nid[sig] = nid;
+ nid_width[nid] = GetSize(sig);
}
- int dump_wire(RTLIL::Wire* wire)
+ void export_cell(Cell *cell)
{
- if(basic_wires[wire->name])
+ log_assert(cell_recursion_guard.count(cell) == 0);
+ cell_recursion_guard.insert(cell);
+ btorf_push(log_id(cell));
+
+ if (cell->type.in("$add", "$sub", "$and", "$or", "$xor", "$xnor", "$shl", "$sshl", "$shr", "$sshr", "$shift", "$shiftx",
+ "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_"))
{
- log("writing wire %s\n", cstr(wire->name));
- auto it = line_ref.find(wire->name);
- if(it==std::end(line_ref))
+ string btor_op;
+ if (cell->type == "$add") btor_op = "add";
+ if (cell->type == "$sub") btor_op = "sub";
+ if (cell->type.in("$shl", "$sshl")) btor_op = "sll";
+ if (cell->type == "$shr") btor_op = "srl";
+ if (cell->type == "$sshr") btor_op = "sra";
+ if (cell->type.in("$shift", "$shiftx")) btor_op = "shift";
+ if (cell->type.in("$and", "$_AND_")) btor_op = "and";
+ if (cell->type.in("$or", "$_OR_")) btor_op = "or";
+ if (cell->type.in("$xor", "$_XOR_")) btor_op = "xor";
+ if (cell->type == "$_NAND_") btor_op = "nand";
+ if (cell->type == "$_NOR_") btor_op = "nor";
+ if (cell->type.in("$xnor", "$_XNOR_")) btor_op = "xnor";
+ log_assert(!btor_op.empty());
+
+ int width = GetSize(cell->getPort("\\Y"));
+ width = std::max(width, GetSize(cell->getPort("\\A")));
+ width = std::max(width, GetSize(cell->getPort("\\B")));
+
+ bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false;
+ bool b_signed = cell->hasParam("\\B_SIGNED") ? cell->getParam("\\B_SIGNED").as_bool() : false;
+
+ if (btor_op == "shift" && !b_signed)
+ btor_op = "srl";
+
+ if (cell->type.in("$shl", "$sshl", "$shr", "$sshr"))
+ b_signed = false;
+
+ if (cell->type == "$sshr" && !a_signed)
+ btor_op = "srl";
+
+ int sid = get_bv_sid(width);
+ int nid;
+
+ if (btor_op == "shift")
{
- ++line_num;
- line_ref[wire->name]=line_num;
- str = stringf("%d var %d %s", line_num, wire->width, cstr(wire->name));
- f << stringf("%s\n", str.c_str());
- return line_num;
+ int nid_a = get_sig_nid(cell->getPort("\\A"), width, false);
+ int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed);
+
+ int nid_r = next_nid++;
+ btorf("%d srl %d %d %d\n", nid_r, sid, nid_a, nid_b);
+
+ int nid_b_neg = next_nid++;
+ btorf("%d neg %d %d\n", nid_b_neg, sid, nid_b);
+
+ int nid_l = next_nid++;
+ btorf("%d sll %d %d %d\n", nid_l, sid, nid_a, nid_b_neg);
+
+ int sid_bit = get_bv_sid(1);
+ int nid_zero = get_sig_nid(Const(0, width));
+ int nid_b_ltz = next_nid++;
+ btorf("%d slt %d %d %d\n", nid_b_ltz, sid_bit, nid_b, nid_zero);
+
+ nid = next_nid++;
+ btorf("%d ite %d %d %d %d\n", nid, sid, nid_b_ltz, nid_l, nid_r);
}
- else return it->second;
+ else
+ {
+ int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed);
+ int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed);
+
+ nid = next_nid++;
+ btorf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b);
+ }
+
+ SigSpec sig = sigmap(cell->getPort("\\Y"));
+
+ if (GetSize(sig) < width) {
+ int sid = get_bv_sid(GetSize(sig));
+ int nid2 = next_nid++;
+ btorf("%d slice %d %d %d 0\n", nid2, sid, nid, GetSize(sig)-1);
+ nid = nid2;
+ }
+
+ add_nid_sig(nid, sig);
+ goto okay;
}
- else // case when the wire is not basic wire
+
+ if (cell->type.in("$_ANDNOT_", "$_ORNOT_"))
{
- log("case of non-basic wire - %s\n", cstr(wire->name));
- auto it = line_ref.find(wire->name);
- if(it==std::end(line_ref))
- {
- std::set<WireInfo, WireInfoOrder>& dep_set = inter_wire_map.at(wire->name);
- int wire_line = 0;
- int wire_width = 0;
- for(auto dep_set_it=dep_set.begin(); dep_set_it!=dep_set.end(); ++dep_set_it)
- {
- RTLIL::IdString cell_id = dep_set_it->cell_name;
- if(cell_id == curr_cell)
- break;
- log(" -- found cell %s\n", cstr(cell_id));
- RTLIL::Cell* cell = module->cells_.at(cell_id);
- const RTLIL::SigSpec* cell_output = get_cell_output(cell);
- int cell_line = dump_cell(cell);
-
- if(dep_set.size()==1 && wire->width == cell_output->size())
- {
- wire_line = cell_line;
- break;
- }
- else
- {
- int prev_wire_line=0; //previously dumped wire line
- int start_bit=0;
- for(unsigned j=0; j<cell_output->chunks().size(); ++j)
- {
- start_bit+=cell_output->chunks().at(j).width;
- if(cell_output->chunks().at(j).wire->name == wire->name)
- {
- prev_wire_line = wire_line;
- wire_line = ++line_num;
- str = stringf("%d slice %d %d %d %d;1", line_num, cell_output->chunks().at(j).width,
- cell_line, start_bit-1, start_bit-cell_output->chunks().at(j).width);
- f << stringf("%s\n", str.c_str());
- wire_width += cell_output->chunks().at(j).width;
- if(prev_wire_line!=0)
- {
- ++line_num;
- str = stringf("%d concat %d %d %d", line_num, wire_width, wire_line, prev_wire_line);
- f << stringf("%s\n", str.c_str());
- wire_line = line_num;
- }
- }
- }
- }
- }
- if(dep_set.size()==0)
- {
- log(" - checking sigmap\n");
- RTLIL::SigSpec s = RTLIL::SigSpec(wire);
- wire_line = dump_sigspec(&s, s.size());
- line_ref[wire->name]=wire_line;
- }
- line_ref[wire->name]=wire_line;
- return wire_line;
+ int sid = get_bv_sid(1);
+ int nid_a = get_sig_nid(cell->getPort("\\A"));
+ int nid_b = get_sig_nid(cell->getPort("\\B"));
+
+ int nid1 = next_nid++;
+ int nid2 = next_nid++;
+
+ if (cell->type == "$_ANDNOT_") {
+ btorf("%d not %d %d\n", nid1, sid, nid_b);
+ btorf("%d and %d %d %d\n", nid2, sid, nid_a, nid1);
}
- else
- {
- log(" -- already processed wire\n");
- return it->second;
+
+ if (cell->type == "$_ORNOT_") {
+ btorf("%d not %d %d\n", nid1, sid, nid_b);
+ btorf("%d or %d %d %d\n", nid2, sid, nid_a, nid1);
}
+
+ SigSpec sig = sigmap(cell->getPort("\\Y"));
+ add_nid_sig(nid2, sig);
+ goto okay;
}
- log_abort();
- return -1;
- }
- int dump_memory(const RTLIL::Memory* memory)
- {
- log("writing memory %s\n", cstr(memory->name));
- auto it = line_ref.find(memory->name);
- if(it==std::end(line_ref))
+ if (cell->type.in("$_OAI3_", "$_AOI3_"))
{
- ++line_num;
- int address_bits = ceil_log2(memory->size);
- str = stringf("%d array %d %d", line_num, memory->width, address_bits);
- line_ref[memory->name]=line_num;
- f << stringf("%s\n", str.c_str());
- return line_num;
+ int sid = get_bv_sid(1);
+ int nid_a = get_sig_nid(cell->getPort("\\A"));
+ int nid_b = get_sig_nid(cell->getPort("\\B"));
+ int nid_c = get_sig_nid(cell->getPort("\\C"));
+
+ int nid1 = next_nid++;
+ int nid2 = next_nid++;
+ int nid3 = next_nid++;
+
+ if (cell->type == "$_OAI3_") {
+ btorf("%d or %d %d %d\n", nid1, sid, nid_a, nid_b);
+ btorf("%d and %d %d %d\n", nid2, sid, nid1, nid_c);
+ btorf("%d not %d %d\n", nid3, sid, nid2);
+ }
+
+ if (cell->type == "$_AOI3_") {
+ btorf("%d and %d %d %d\n", nid1, sid, nid_a, nid_b);
+ btorf("%d or %d %d %d\n", nid2, sid, nid1, nid_c);
+ btorf("%d not %d %d\n", nid3, sid, nid2);
+ }
+
+ SigSpec sig = sigmap(cell->getPort("\\Y"));
+ add_nid_sig(nid3, sig);
+ goto okay;
}
- else return it->second;
- }
- int dump_memory_next(const RTLIL::Memory* memory)
- {
- auto mem_it = line_ref.find(memory->name);
- int address_bits = ceil_log2(memory->size);
- if(mem_it==std::end(line_ref))
- {
- log("can not write next of a memory that is not dumped yet\n");
- log_abort();
- }
- else
- {
- auto acond_list_it = mem_next.find(mem_it->second);
- if(acond_list_it!=std::end(mem_next))
+ if (cell->type.in("$_OAI4_", "$_AOI4_"))
{
- std::set<std::pair<int,int>>& cond_list = acond_list_it->second;
- if(cond_list.empty())
- {
- return 0;
- }
- auto it=cond_list.begin();
- ++line_num;
- str = stringf("%d acond %d %d %d %d %d", line_num, memory->width, address_bits, it->first, it->second, mem_it->second);
- f << stringf("%s\n", str.c_str());
- ++it;
- for(; it!=cond_list.end(); ++it)
- {
- ++line_num;
- str = stringf("%d acond %d %d %d %d %d", line_num, memory->width, address_bits, it->first, it->second, line_num-1);
- f << stringf("%s\n", str.c_str());
- }
- ++line_num;
- str = stringf("%d anext %d %d %d %d", line_num, memory->width, address_bits, mem_it->second, line_num-1);
- f << stringf("%s\n", str.c_str());
- return 1;
+ int sid = get_bv_sid(1);
+ int nid_a = get_sig_nid(cell->getPort("\\A"));
+ int nid_b = get_sig_nid(cell->getPort("\\B"));
+ int nid_c = get_sig_nid(cell->getPort("\\C"));
+ int nid_d = get_sig_nid(cell->getPort("\\D"));
+
+ int nid1 = next_nid++;
+ int nid2 = next_nid++;
+ int nid3 = next_nid++;
+ int nid4 = next_nid++;
+
+ if (cell->type == "$_OAI4_") {
+ btorf("%d or %d %d %d\n", nid1, sid, nid_a, nid_b);
+ btorf("%d or %d %d %d\n", nid2, sid, nid_c, nid_d);
+ btorf("%d and %d %d %d\n", nid3, sid, nid1, nid2);
+ btorf("%d not %d %d\n", nid4, sid, nid3);
+ }
+
+ if (cell->type == "$_AOI4_") {
+ btorf("%d and %d %d %d\n", nid1, sid, nid_a, nid_b);
+ btorf("%d and %d %d %d\n", nid2, sid, nid_c, nid_d);
+ btorf("%d or %d %d %d\n", nid3, sid, nid1, nid2);
+ btorf("%d not %d %d\n", nid4, sid, nid3);
+ }
+
+ SigSpec sig = sigmap(cell->getPort("\\Y"));
+ add_nid_sig(nid4, sig);
+ goto okay;
}
- return 0;
- }
- }
- int dump_const(const RTLIL::Const* data, int width, int offset)
- {
- log("writing const \n");
- if((data->flags & RTLIL::CONST_FLAG_STRING) == 0)
+ if (cell->type.in("$lt", "$le", "$eq", "$eqx", "$ne", "$nex", "$ge", "$gt"))
{
- if(width<0)
- width = data->bits.size() - offset;
+ string btor_op;
+ if (cell->type == "$lt") btor_op = "lt";
+ if (cell->type == "$le") btor_op = "lte";
+ if (cell->type.in("$eq", "$eqx")) btor_op = "eq";
+ if (cell->type.in("$ne", "$nex")) btor_op = "ne";
+ if (cell->type == "$ge") btor_op = "gte";
+ if (cell->type == "$gt") btor_op = "gt";
+ log_assert(!btor_op.empty());
+
+ int width = 1;
+ width = std::max(width, GetSize(cell->getPort("\\A")));
+ width = std::max(width, GetSize(cell->getPort("\\B")));
+
+ bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false;
+ bool b_signed = cell->hasParam("\\B_SIGNED") ? cell->getParam("\\B_SIGNED").as_bool() : false;
+
+ int sid = get_bv_sid(1);
+ int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed);
+ int nid_b = get_sig_nid(cell->getPort("\\B"), width, b_signed);
+
+ int nid = next_nid++;
+ if (cell->type.in("$lt", "$le", "$ge", "$gt")) {
+ btorf("%d %c%s %d %d %d\n", nid, a_signed || b_signed ? 's' : 'u', btor_op.c_str(), sid, nid_a, nid_b);
+ } else {
+ btorf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b);
+ }
- std::string data_str = data->as_string();
- //if(offset > 0)
- data_str = data_str.substr(offset, width);
+ SigSpec sig = sigmap(cell->getPort("\\Y"));
- ++line_num;
- str = stringf("%d const %d %s", line_num, width, data_str.c_str());
- f << stringf("%s\n", str.c_str());
- return line_num;
+ if (GetSize(sig) > 1) {
+ int sid = get_bv_sid(GetSize(sig));
+ int nid2 = next_nid++;
+ btorf("%d uext %d %d %d\n", nid2, sid, nid, GetSize(sig) - 1);
+ nid = nid2;
+ }
+
+ add_nid_sig(nid, sig);
+ goto okay;
}
- else
- log("writing const error\n");
- log_abort();
- return -1;
- }
- int dump_sigchunk(const RTLIL::SigChunk* chunk)
- {
- log("writing sigchunk\n");
- int l=-1;
- if(chunk->wire == NULL)
+ if (cell->type.in("$not", "$neg", "$_NOT_"))
{
- RTLIL::Const data_const(chunk->data);
- l=dump_const(&data_const, chunk->width, chunk->offset);
+ string btor_op;
+ if (cell->type.in("$not", "$_NOT_")) btor_op = "not";
+ if (cell->type == "$neg") btor_op = "neg";
+ log_assert(!btor_op.empty());
+
+ int width = GetSize(cell->getPort("\\Y"));
+ width = std::max(width, GetSize(cell->getPort("\\A")));
+
+ bool a_signed = cell->hasParam("\\A_SIGNED") ? cell->getParam("\\A_SIGNED").as_bool() : false;
+
+ int sid = get_bv_sid(width);
+ int nid_a = get_sig_nid(cell->getPort("\\A"), width, a_signed);
+
+ int nid = next_nid++;
+ btorf("%d %s %d %d\n", nid, btor_op.c_str(), sid, nid_a);
+
+ SigSpec sig = sigmap(cell->getPort("\\Y"));
+
+ if (GetSize(sig) < width) {
+ int sid = get_bv_sid(GetSize(sig));
+ int nid2 = next_nid++;
+ btorf("%d slice %d %d %d 0\n", nid2, sid, nid, GetSize(sig)-1);
+ nid = nid2;
+ }
+
+ add_nid_sig(nid, sig);
+ goto okay;
}
- else
+
+ if (cell->type.in("$logic_and", "$logic_or", "$logic_not"))
{
- if (chunk->width == chunk->wire->width && chunk->offset == 0)
- l = dump_wire(chunk->wire);
+ string btor_op;
+ if (cell->type == "$logic_and") btor_op = "and";
+ if (cell->type == "$logic_or") btor_op = "or";
+ if (cell->type == "$logic_not") btor_op = "not";
+ log_assert(!btor_op.empty());
+
+ int sid = get_bv_sid(1);
+ int nid_a = get_sig_nid(cell->getPort("\\A"));
+ int nid_b = btor_op != "not" ? get_sig_nid(cell->getPort("\\B")) : 0;
+
+ if (GetSize(cell->getPort("\\A")) > 1) {
+ int nid_red_a = next_nid++;
+ btorf("%d redor %d %d\n", nid_red_a, sid, nid_a);
+ nid_a = nid_red_a;
+ }
+
+ if (btor_op != "not" && GetSize(cell->getPort("\\B")) > 1) {
+ int nid_red_b = next_nid++;
+ btorf("%d redor %d %d\n", nid_red_b, sid, nid_b);
+ nid_b = nid_red_b;
+ }
+
+ int nid = next_nid++;
+ if (btor_op != "not")
+ btorf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b);
else
- {
- int wire_line_num = dump_wire(chunk->wire);
- log_assert(wire_line_num>0);
- ++line_num;
- str = stringf("%d slice %d %d %d %d;2", line_num, chunk->width, wire_line_num,
- chunk->width + chunk->offset - 1, chunk->offset);
- f << stringf("%s\n", str.c_str());
- l = line_num;
+ btorf("%d %s %d %d\n", nid, btor_op.c_str(), sid, nid_a);
+
+ SigSpec sig = sigmap(cell->getPort("\\Y"));
+
+ if (GetSize(sig) > 1) {
+ int sid = get_bv_sid(GetSize(sig));
+ int zeros_nid = get_sig_nid(Const(0, GetSize(sig)-1));
+ int nid2 = next_nid++;
+ btorf("%d concat %d %d %d\n", nid2, sid, zeros_nid, nid);
+ nid = nid2;
}
+
+ add_nid_sig(nid, sig);
+ goto okay;
}
- return l;
- }
- int dump_sigspec(const RTLIL::SigSpec* sig, int expected_width)
- {
- log("writing sigspec\n");
- RTLIL::SigSpec s = sigmap(*sig);
- int l = -1;
- auto it = sig_ref.find(s);
- if(it == std::end(sig_ref))
+ if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool", "$reduce_xor", "$reduce_xnor"))
{
- if (s.is_chunk())
- {
- l = dump_sigchunk(&s.chunks().front());
+ string btor_op;
+ if (cell->type == "$reduce_and") btor_op = "redand";
+ if (cell->type.in("$reduce_or", "$reduce_bool")) btor_op = "redor";
+ if (cell->type.in("$reduce_xor", "$reduce_xnor")) btor_op = "redxor";
+ log_assert(!btor_op.empty());
+
+ int sid = get_bv_sid(1);
+ int nid_a = get_sig_nid(cell->getPort("\\A"));
+
+ int nid = next_nid++;
+ btorf("%d %s %d %d\n", nid, btor_op.c_str(), sid, nid_a);
+
+ if (cell->type == "$reduce_xnor") {
+ int nid2 = next_nid++;
+ btorf("%d not %d %d %d\n", nid2, sid, nid);
+ nid = nid2;
}
- else
- {
- int l1, l2, w1, w2;
- l1 = dump_sigchunk(&s.chunks().front());
- log_assert(l1>0);
- w1 = s.chunks().front().width;
- for (unsigned i=1; i < s.chunks().size(); ++i)
- {
- l2 = dump_sigchunk(&s.chunks().at(i));
- log_assert(l2>0);
- w2 = s.chunks().at(i).width;
- ++line_num;
- str = stringf("%d concat %d %d %d", line_num, w1+w2, l2, l1);
- f << stringf("%s\n", str.c_str());
- l1=line_num;
- w1+=w2;
- }
- l = line_num;
+
+ SigSpec sig = sigmap(cell->getPort("\\Y"));
+
+ if (GetSize(sig) > 1) {
+ int sid = get_bv_sid(GetSize(sig));
+ int zeros_nid = get_sig_nid(Const(0, GetSize(sig)-1));
+ int nid2 = next_nid++;
+ btorf("%d concat %d %d %d\n", nid2, sid, zeros_nid, nid);
+ nid = nid2;
}
- sig_ref[s] = l;
+
+ add_nid_sig(nid, sig);
+ goto okay;
}
- else
+
+ if (cell->type.in("$mux", "$_MUX_"))
{
- l = it->second;
+ SigSpec sig_a = sigmap(cell->getPort("\\A"));
+ SigSpec sig_b = sigmap(cell->getPort("\\B"));
+ SigSpec sig_s = sigmap(cell->getPort("\\S"));
+ SigSpec sig_y = sigmap(cell->getPort("\\Y"));
+
+ int nid_a = get_sig_nid(sig_a);
+ int nid_b = get_sig_nid(sig_b);
+ int nid_s = get_sig_nid(sig_s);
+
+ int sid = get_bv_sid(GetSize(sig_y));
+ int nid = next_nid++;
+ btorf("%d ite %d %d %d %d\n", nid, sid, nid_s, nid_b, nid_a);
+
+ add_nid_sig(nid, sig_y);
+ goto okay;
}
- if (expected_width != s.size())
+ if (cell->type == "$pmux")
{
- log(" - changing width of sigspec\n");
- //TODO: this block may not be needed anymore, due to explicit type conversion by "splice" command
- if(expected_width > s.size())
- {
- //TODO: case the signal is signed
- ++line_num;
- str = stringf ("%d zero %d", line_num, expected_width - s.size());
- f << stringf("%s\n", str.c_str());
- ++line_num;
- str = stringf ("%d concat %d %d %d", line_num, expected_width, line_num-1, l);
- f << stringf("%s\n", str.c_str());
- l = line_num;
+ SigSpec sig_a = sigmap(cell->getPort("\\A"));
+ SigSpec sig_b = sigmap(cell->getPort("\\B"));
+ SigSpec sig_s = sigmap(cell->getPort("\\S"));
+ SigSpec sig_y = sigmap(cell->getPort("\\Y"));
+
+ int width = GetSize(sig_a);
+ int sid = get_bv_sid(width);
+ int nid = get_sig_nid(sig_a);
+
+ for (int i = 0; i < GetSize(sig_s); i++) {
+ int nid_b = get_sig_nid(sig_b.extract(i*width, width));
+ int nid_s = get_sig_nid(sig_s.extract(i));
+ int nid2 = next_nid++;
+ btorf("%d ite %d %d %d %d\n", nid2, sid, nid_s, nid_b, nid);
+ nid = nid2;
}
- else if(expected_width < s.size())
- {
- ++line_num;
- str = stringf ("%d slice %d %d %d %d;3", line_num, expected_width, l, expected_width-1, 0);
- f << stringf("%s\n", str.c_str());
- l = line_num;
+
+ add_nid_sig(nid, sig_y);
+ goto okay;
+ }
+
+ if (cell->type.in("$dff", "$ff", "$_DFF_P_", "$_DFF_N", "$_FF_"))
+ {
+ SigSpec sig_d = sigmap(cell->getPort("\\D"));
+ SigSpec sig_q = sigmap(cell->getPort("\\Q"));
+
+ IdString symbol;
+
+ if (sig_q.is_wire()) {
+ Wire *w = sig_q.as_wire();
+ if (w->port_id == 0) {
+ statewires.insert(w);
+ symbol = w->name;
+ }
+ }
+
+ int sid = get_bv_sid(GetSize(sig_q));
+ int nid = next_nid++;
+
+ if (symbol.empty())
+ btorf("%d state %d\n", nid, sid);
+ else
+ btorf("%d state %d %s\n", nid, sid, log_id(symbol));
+
+ Const initval;
+ for (int i = 0; i < GetSize(sig_q); i++)
+ if (initbits.count(sig_q[i]))
+ initval.bits.push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0);
+ else
+ initval.bits.push_back(State::Sx);
+
+ if (!initval.is_fully_undef()) {
+ int nid_init_val = get_sig_nid(initval);
+ int nid_init = next_nid++;
+ if (verbose)
+ btorf("; initval = %s\n", log_signal(initval));
+ btorf("%d init %d %d %d\n", nid_init, sid, nid, nid_init_val);
}
+
+ ff_todo.push_back(make_pair(nid, cell));
+ add_nid_sig(nid, sig_q);
+ goto okay;
}
- log_assert(l>0);
- return l;
- }
- int dump_cell(const RTLIL::Cell* cell)
- {
- auto it = line_ref.find(cell->name);
- if(it==std::end(line_ref))
+ if (cell->type.in("$anyconst", "$anyseq"))
{
- curr_cell = cell->name;
- //assert cell
- if(cell->type == "$assert")
- {
- log("writing assert cell - %s\n", cstr(cell->type));
- const RTLIL::SigSpec* expr = &cell->getPort(RTLIL::IdString("\\A"));
- const RTLIL::SigSpec* en = &cell->getPort(RTLIL::IdString("\\EN"));
- log_assert(expr->size() == 1);
- log_assert(en->size() == 1);
- int expr_line = dump_sigspec(expr, 1);
- int en_line = dump_sigspec(en, 1);
- int one_line = ++line_num;
- str = stringf("%d one 1", line_num);
- f << stringf("%s\n", str.c_str());
- ++line_num;
- str = stringf("%d %s %d %d %d", line_num, cell_type_translation.at("$eq").c_str(), 1, en_line, one_line);
- f << stringf("%s\n", str.c_str());
- ++line_num;
- str = stringf("%d %s %d %d %d %d", line_num, cell_type_translation.at("$mux").c_str(), 1, line_num-1,
- expr_line, one_line);
- f << stringf("%s\n", str.c_str());
- int cell_line = ++line_num;
- str = stringf("%d %s %d %d", line_num, cell_type_translation.at("$assert").c_str(), 1, -1*(line_num-1));
- //multiplying the line number with -1, which means logical negation
- //the reason for negative sign is that the properties in btor are given as "negation of the original property"
- //bug identified by bobosoft
- //http://www.reddit.com/r/yosys/comments/1w3xig/btor_backend_bug/
- f << stringf("%s\n", str.c_str());
- line_ref[cell->name]=cell_line;
+ SigSpec sig_y = sigmap(cell->getPort("\\Y"));
+
+ int sid = get_bv_sid(GetSize(sig_y));
+ int nid = next_nid++;
+
+ btorf("%d state %d\n", nid, sid);
+
+ if (cell->type == "$anyconst") {
+ int nid2 = next_nid++;
+ btorf("%d next %d %d %d\n", nid2, sid, nid, nid);
}
- //unary cells
- else if(cell->type == "$not" || cell->type == "$neg" || cell->type == "$pos" || cell->type == "$reduce_and" ||
- cell->type == "$reduce_or" || cell->type == "$reduce_xor" || cell->type == "$reduce_bool")
+
+ add_nid_sig(nid, sig_y);
+ goto okay;
+ }
+
+ if (cell->type == "$initstate")
+ {
+ SigSpec sig_y = sigmap(cell->getPort("\\Y"));
+
+ if (initstate_nid < 0)
{
- log("writing unary cell - %s\n", cstr(cell->type));
- int w = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int();
- int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int();
- w = w>output_width ? w:output_width; //padding of w
- int l = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), w);
- int cell_line = l;
- if(cell->type != "$pos")
- {
- cell_line = ++line_num;
- bool reduced = (cell->type == "$not" || cell->type == "$neg") ? false : true;
- str = stringf ("%d %s %d %d", cell_line, cell_type_translation.at(cell->type.str()).c_str(), reduced?output_width:w, l);
- f << stringf("%s\n", str.c_str());
- }
- if(output_width < w && (cell->type == "$not" || cell->type == "$neg" || cell->type == "$pos"))
- {
- ++line_num;
- str = stringf ("%d slice %d %d %d %d;4", line_num, output_width, cell_line, output_width-1, 0);
- f << stringf("%s\n", str.c_str());
- cell_line = line_num;
- }
- line_ref[cell->name]=cell_line;
+ int sid = get_bv_sid(1);
+ int one_nid = get_sig_nid(Const(1, 1));
+ int zero_nid = get_sig_nid(Const(0, 1));
+ initstate_nid = next_nid++;
+ btorf("%d state %d\n", initstate_nid, sid);
+ btorf("%d init %d %d %d\n", next_nid++, sid, initstate_nid, one_nid);
+ btorf("%d next %d %d %d\n", next_nid++, sid, initstate_nid, zero_nid);
}
- else if(cell->type == "$reduce_xnor" || cell->type == "$logic_not")//no direct translation in btor
+
+ add_nid_sig(initstate_nid, sig_y);
+ goto okay;
+ }
+
+ if (cell->type == "$mem")
+ {
+ int abits = cell->getParam("\\ABITS").as_int();
+ int width = cell->getParam("\\WIDTH").as_int();
+ int rdports = cell->getParam("\\RD_PORTS").as_int();
+ int wrports = cell->getParam("\\WR_PORTS").as_int();
+
+ Const wr_clk_en = cell->getParam("\\WR_CLK_ENABLE");
+ Const rd_clk_en = cell->getParam("\\RD_CLK_ENABLE");
+
+ bool asyncwr = wr_clk_en.is_fully_zero();
+
+ if (!asyncwr && !wr_clk_en.is_fully_ones())
+ log_error("Memory %s.%s has mixed async/sync write ports.\n",
+ log_id(module), log_id(cell));
+
+ if (!rd_clk_en.is_fully_zero())
+ log_error("Memory %s.%s has sync read ports.\n",
+ log_id(module), log_id(cell));
+
+ SigSpec sig_rd_addr = sigmap(cell->getPort("\\RD_ADDR"));
+ SigSpec sig_rd_data = sigmap(cell->getPort("\\RD_DATA"));
+
+ SigSpec sig_wr_addr = sigmap(cell->getPort("\\WR_ADDR"));
+ SigSpec sig_wr_data = sigmap(cell->getPort("\\WR_DATA"));
+ SigSpec sig_wr_en = sigmap(cell->getPort("\\WR_EN"));
+
+ int data_sid = get_bv_sid(width);
+ int bool_sid = get_bv_sid(1);
+ int sid = get_mem_sid(abits, width);
+ int nid = next_nid++;
+ int nid_head = nid;
+
+ if (cell->name[0] == '$')
+ btorf("%d state %d\n", nid, sid);
+ else
+ btorf("%d state %d %s\n", nid, sid, log_id(cell));
+
+ if (asyncwr)
{
- log("writing unary cell - %s\n", cstr(cell->type));
- int w = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int();
- int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int();
- log_assert(output_width == 1);
- int l = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), w);
- if(cell->type == "$logic_not" && w > 1)
+ for (int port = 0; port < wrports; port++)
{
- ++line_num;
- str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_or").c_str(), output_width, l);
- f << stringf("%s\n", str.c_str());
- }
- else if(cell->type == "$reduce_xnor")
- {
- ++line_num;
- str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_xor").c_str(), output_width, l);
- f << stringf("%s\n", str.c_str());
+ SigSpec wa = sig_wr_addr.extract(port*abits, abits);
+ SigSpec wd = sig_wr_data.extract(port*width, width);
+ SigSpec we = sig_wr_en.extract(port*width, width);
+
+ int wa_nid = get_sig_nid(wa);
+ int wd_nid = get_sig_nid(wd);
+ int we_nid = get_sig_nid(we);
+
+ int nid2 = next_nid++;
+ btorf("%d read %d %d %d\n", nid2, data_sid, nid_head, wa_nid);
+
+ int nid3 = next_nid++;
+ btorf("%d not %d %d\n", nid3, data_sid, we_nid);
+
+ int nid4 = next_nid++;
+ btorf("%d and %d %d %d\n", nid4, data_sid, nid2, nid3);
+
+ int nid5 = next_nid++;
+ btorf("%d and %d %d %d\n", nid5, data_sid, wd_nid, we_nid);
+
+ int nid6 = next_nid++;
+ btorf("%d or %d %d %d\n", nid6, data_sid, nid5, nid4);
+
+ int nid7 = next_nid++;
+ btorf("%d write %d %d %d %d\n", nid7, sid, nid_head, wa_nid, nid6);
+
+ int nid8 = next_nid++;
+ btorf("%d redor %d %d\n", nid8, bool_sid, we_nid);
+
+ int nid9 = next_nid++;
+ btorf("%d ite %d %d %d %d\n", nid9, sid, nid8, nid7, nid_head);
+
+ nid_head = nid9;
}
- ++line_num;
- str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$not").c_str(), output_width, l);
- f << stringf("%s\n", str.c_str());
- line_ref[cell->name]=line_num;
}
- //binary cells
- else if(cell->type == "$and" || cell->type == "$or" || cell->type == "$xor" || cell->type == "$xnor" ||
- cell->type == "$lt" || cell->type == "$le" || cell->type == "$eq" || cell->type == "$ne" ||
- cell->type == "$eqx" || cell->type == "$nex" || cell->type == "$ge" || cell->type == "$gt" )
+
+ for (int port = 0; port < rdports; port++)
{
- log("writing binary cell - %s\n", cstr(cell->type));
- int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int();
- log_assert(!(cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex" ||
- cell->type == "$ge" || cell->type == "$gt") || output_width == 1);
- bool l1_signed = cell->parameters.at(RTLIL::IdString("\\A_SIGNED")).as_bool();
- bool l2_signed YS_ATTRIBUTE(unused) = cell->parameters.at(RTLIL::IdString("\\B_SIGNED")).as_bool();
- int l1_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int();
- int l2_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int();
-
- log_assert(l1_signed == l2_signed);
- l1_width = l1_width > output_width ? l1_width : output_width;
- l1_width = l1_width > l2_width ? l1_width : l2_width;
- l2_width = l2_width > l1_width ? l2_width : l1_width;
-
- int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), l1_width);
- int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), l2_width);
-
- ++line_num;
- std::string op = cell_type_translation.at(cell->type.str());
- if(cell->type == "$lt" || cell->type == "$le" ||
- cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex" ||
- cell->type == "$ge" || cell->type == "$gt")
- {
- if(l1_signed)
- op = s_cell_type_translation.at(cell->type.str());
- }
+ SigSpec ra = sig_rd_addr.extract(port*abits, abits);
+ SigSpec rd = sig_rd_data.extract(port*width, width);
+
+ int ra_nid = get_sig_nid(ra);
+ int rd_nid = next_nid++;
- str = stringf ("%d %s %d %d %d", line_num, op.c_str(), output_width, l1, l2);
- f << stringf("%s\n", str.c_str());
+ btorf("%d read %d %d %d\n", rd_nid, data_sid, nid_head, ra_nid);
- line_ref[cell->name]=line_num;
+ add_nid_sig(rd_nid, rd);
}
- else if(cell->type == "$add" || cell->type == "$sub" || cell->type == "$mul" || cell->type == "$div" ||
- cell->type == "$mod" )
- {
- //TODO: division by zero case
- log("writing binary cell - %s\n", cstr(cell->type));
- int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int();
- bool l1_signed = cell->parameters.at(RTLIL::IdString("\\A_SIGNED")).as_bool();
- bool l2_signed = cell->parameters.at(RTLIL::IdString("\\B_SIGNED")).as_bool();
- int l1_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int();
- int l2_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int();
-
- log_assert(l1_signed == l2_signed);
- l1_width = l1_width > output_width ? l1_width : output_width;
- l1_width = l1_width > l2_width ? l1_width : l2_width;
- l2_width = l2_width > l1_width ? l2_width : l1_width;
-
- int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), l1_width);
- int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), l2_width);
-
- ++line_num;
- std::string op = cell_type_translation.at(cell->type.str());
- if(cell->type == "$div" && l1_signed)
- op = s_cell_type_translation.at(cell->type.str());
- else if(cell->type == "$mod")
- {
- if(l1_signed)
- op = s_cell_type_translation.at("$modx");
- else if(l2_signed)
- op = s_cell_type_translation.at("$mody");
- }
- str = stringf ("%d %s %d %d %d", line_num, op.c_str(), l1_width, l1, l2);
- f << stringf("%s\n", str.c_str());
- if(output_width < l1_width)
- {
- ++line_num;
- str = stringf ("%d slice %d %d %d %d;5", line_num, output_width, line_num-1, output_width-1, 0);
- f << stringf("%s\n", str.c_str());
- }
- line_ref[cell->name]=line_num;
+ if (!asyncwr)
+ {
+ ff_todo.push_back(make_pair(nid, cell));
}
- else if(cell->type == "$shr" || cell->type == "$shl" || cell->type == "$sshr" || cell->type == "$sshl" || cell->type == "$shift" || cell->type == "$shiftx")
+ else
{
- log("writing binary cell - %s\n", cstr(cell->type));
- int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int();
- bool l1_signed = cell->parameters.at(RTLIL::IdString("\\A_SIGNED")).as_bool();
- //bool l2_signed = cell->parameters.at(RTLIL::IdString("\\B_SIGNED")).as_bool();
- int l1_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int();
- l1_width = 1 << ceil_log2(l1_width);
- int l2_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int();
- //log_assert(l2_width <= ceil_log2(l1_width)) );
- int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), l1_width);
- int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), ceil_log2(l1_width));
- int cell_output = ++line_num;
- str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(), l1_width, l1, l2);
- f << stringf("%s\n", str.c_str());
-
- if(l2_width > ceil_log2(l1_width))
- {
- int extra_width = l2_width - ceil_log2(l1_width);
- l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), l2_width);
- ++line_num;
- str = stringf ("%d slice %d %d %d %d;6", line_num, extra_width, l2, l2_width-1, l2_width-extra_width);
- f << stringf("%s\n", str.c_str());
- ++line_num;
- str = stringf ("%d one %d", line_num, extra_width);
- f << stringf("%s\n", str.c_str());
- int mux = ++line_num;
- str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at("$gt").c_str(), 1, line_num-2, line_num-1);
- f << stringf("%s\n", str.c_str());
- ++line_num;
- str = stringf("%d %s %d", line_num, l1_signed && cell->type == "$sshr" ? "ones":"zero", l1_width);
- f << stringf("%s\n", str.c_str());
- ++line_num;
- str = stringf ("%d %s %d %d %d %d", line_num, cell_type_translation.at("$mux").c_str(), l1_width, mux, line_num-1, cell_output);
- f << stringf("%s\n", str.c_str());
- cell_output = line_num;
- }
+ int nid2 = next_nid++;
+ btorf("%d next %d %d %d\n", nid2, sid, nid, nid_head);
+ }
- if(output_width < l1_width)
- {
- ++line_num;
- str = stringf ("%d slice %d %d %d %d;5", line_num, output_width, cell_output, output_width-1, 0);
- f << stringf("%s\n", str.c_str());
- cell_output = line_num;
+ goto okay;
+ }
+
+ log_error("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
+
+ okay:
+ btorf_pop(log_id(cell));
+ cell_recursion_guard.erase(cell);
+ }
+
+ int get_sig_nid(SigSpec sig, int to_width = -1, bool is_signed = false)
+ {
+ int nid = -1;
+ sigmap.apply(sig);
+
+ for (auto bit : sig)
+ if (bit == State::Sx)
+ goto has_undef_bits;
+
+ if (0)
+ {
+ has_undef_bits:
+ SigSpec sig_mask_undef, sig_noundef;
+ int first_undef = -1;
+
+ for (int i = 0; i < GetSize(sig); i++)
+ if (sig[i] == State::Sx) {
+ if (first_undef < 0)
+ first_undef = i;
+ sig_mask_undef.append(State::S1);
+ sig_noundef.append(State::S0);
+ } else {
+ sig_mask_undef.append(State::S0);
+ sig_noundef.append(sig[i]);
}
- line_ref[cell->name] = cell_output;
- }
- else if(cell->type == "$logic_and" || cell->type == "$logic_or")//no direct translation in btor
+
+ if (to_width < 0 || first_undef < to_width)
{
- log("writing binary cell - %s\n", cstr(cell->type));
- int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int();
- log_assert(output_width == 1);
- int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), output_width);
- int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), output_width);
- int l1_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int();
- int l2_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int();
- if(l1_width >1)
- {
- ++line_num;
- str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_or").c_str(), output_width, l1);
- f << stringf("%s\n", str.c_str());
- l1 = line_num;
+ int sid = get_bv_sid(GetSize(sig));
+
+ int nid_input = next_nid++;
+ btorf("%d input %d\n", nid_input, sid);
+
+ int nid_masked_input;
+ if (sig_mask_undef.is_fully_ones()) {
+ nid_masked_input = nid_input;
+ } else {
+ int nid_mask_undef = get_sig_nid(sig_mask_undef);
+ nid_masked_input = next_nid++;
+ btorf("%d and %d %d %d\n", nid_masked_input, sid, nid_input, nid_mask_undef);
}
- if(l2_width > 1)
- {
- ++line_num;
- str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_or").c_str(), output_width, l2);
- f << stringf("%s\n", str.c_str());
- l2 = line_num;
- }
- if(cell->type == "$logic_and")
- {
- ++line_num;
- str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at("$and").c_str(), output_width, l1, l2);
- }
- else if(cell->type == "$logic_or")
- {
- ++line_num;
- str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at("$or").c_str(), output_width, l1, l2);
+
+ if (sig_noundef.is_fully_zero()) {
+ nid = nid_masked_input;
+ } else {
+ int nid_noundef = get_sig_nid(sig_noundef);
+ nid = next_nid++;
+ btorf("%d or %d %d %d\n", nid, sid, nid_masked_input, nid_noundef);
}
- f << stringf("%s\n", str.c_str());
- line_ref[cell->name]=line_num;
- }
- //multiplexers
- else if(cell->type == "$mux")
- {
- log("writing mux cell\n");
- int output_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int();
- int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), output_width);
- int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), output_width);
- int s = dump_sigspec(&cell->getPort(RTLIL::IdString("\\S")), 1);
- ++line_num;
- str = stringf ("%d %s %d %d %d %d",
- line_num, cell_type_translation.at(cell->type.str()).c_str(), output_width, s, l2, l1);
- //if s is 0 then l1, if s is 1 then l2 //according to the implementation of mux cell
- f << stringf("%s\n", str.c_str());
- line_ref[cell->name]=line_num;
+
+ goto extend_or_trim;
}
- else if(cell->type == "$pmux")
- {
- log("writing pmux cell\n");
- int output_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int();
- int select_width = cell->parameters.at(RTLIL::IdString("\\S_WIDTH")).as_int();
- int default_case = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), output_width);
- int cases = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), output_width*select_width);
- int select = dump_sigspec(&cell->getPort(RTLIL::IdString("\\S")), select_width);
- int *c = new int[select_width];
-
- for (int i=0; i<select_width; ++i)
- {
- ++line_num;
- str = stringf ("%d slice 1 %d %d %d", line_num, select, i, i);
- f << stringf("%s\n", str.c_str());
- c[i] = line_num;
- ++line_num;
- str = stringf ("%d slice %d %d %d %d", line_num, output_width, cases, i*output_width+output_width-1,
- i*output_width);
- f << stringf("%s\n", str.c_str());
- }
-
- ++line_num;
- str = stringf ("%d cond %d %d %d %d", line_num, output_width, c[select_width-1], c[select_width-1]+1, default_case);
- f << stringf("%s\n", str.c_str());
-
- for (int i=select_width-2; i>=0; --i)
- {
- ++line_num;
- str = stringf ("%d cond %d %d %d %d", line_num, output_width, c[i], c[i]+1, line_num-1);
- f << stringf("%s\n", str.c_str());
- }
-
- line_ref[cell->name]=line_num;
- }
- //registers
- else if(cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffsr")
+
+ sig = sig_noundef;
+ }
+
+ if (sig_nid.count(sig) == 0)
+ {
+ // <nid>, <bitidx>
+ vector<pair<int, int>> nidbits;
+
+ // collect all bits
+ for (int i = 0; i < GetSize(sig); i++)
{
- //TODO: remodelling of adff cells
- log("writing cell - %s\n", cstr(cell->type));
- int output_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int();
- log(" - width is %d\n", output_width);
- int cond = dump_sigspec(&cell->getPort(RTLIL::IdString("\\CLK")), 1);
- bool polarity = cell->parameters.at(RTLIL::IdString("\\CLK_POLARITY")).as_bool();
- const RTLIL::SigSpec* cell_output = &cell->getPort(RTLIL::IdString("\\Q"));
- int value = dump_sigspec(&cell->getPort(RTLIL::IdString("\\D")), output_width);
- unsigned start_bit = 0;
- for(unsigned i=0; i<cell_output->chunks().size(); ++i)
+ SigBit bit = sig[i];
+
+ if (bit_nid.count(bit) == 0)
{
- output_width = cell_output->chunks().at(i).width;
- log_assert( output_width == cell_output->chunks().at(i).wire->width);//full reg is given the next value
- int reg = dump_wire(cell_output->chunks().at(i).wire);//register
- int slice = value;
- if(cell_output->chunks().size()>1)
+ if (bit.wire == nullptr)
{
- start_bit+=output_width;
- slice = ++line_num;
- str = stringf ("%d slice %d %d %d %d;", line_num, output_width, value, start_bit-1,
- start_bit-output_width);
- f << stringf("%s\n", str.c_str());
- }
- if(cell->type == "$dffsr")
- {
- int sync_reset = dump_sigspec(&cell->getPort(RTLIL::IdString("\\CLR")), 1);
- bool sync_reset_pol = cell->parameters.at(RTLIL::IdString("\\CLR_POLARITY")).as_bool();
- int sync_reset_value = dump_sigspec(&cell->getPort(RTLIL::IdString("\\SET")),
- output_width);
- bool sync_reset_value_pol = cell->parameters.at(RTLIL::IdString("\\SET_POLARITY")).as_bool();
- ++line_num;
- str = stringf ("%d %s %d %s%d %s%d %d", line_num, cell_type_translation.at("$mux").c_str(),
- output_width, sync_reset_pol ? "":"-", sync_reset, sync_reset_value_pol? "":"-",
- sync_reset_value, slice);
- f << stringf("%s\n", str.c_str());
- slice = line_num;
- }
- ++line_num;
- str = stringf ("%d %s %d %s%d %d %d", line_num, cell_type_translation.at("$mux").c_str(),
- output_width, polarity?"":"-", cond, slice, reg);
+ Const c(bit.data);
+
+ while (i+GetSize(c) < GetSize(sig) && sig[i+GetSize(c)].wire == nullptr)
+ c.bits.push_back(sig[i+GetSize(c)].data);
+
+ if (consts.count(c) == 0) {
+ int sid = get_bv_sid(GetSize(c));
+ int nid = next_nid++;
+ btorf("%d const %d %s\n", nid, sid, c.as_string().c_str());
+ consts[c] = nid;
+ nid_width[nid] = GetSize(c);
+ }
+
+ int nid = consts.at(c);
- f << stringf("%s\n", str.c_str());
- int next = line_num;
- if(cell->type == "$adff")
+ for (int j = 0; j < GetSize(c); j++)
+ nidbits.push_back(make_pair(nid, j));
+
+ i += GetSize(c)-1;
+ continue;
+ }
+ else
{
- int async_reset = dump_sigspec(&cell->getPort(RTLIL::IdString("\\ARST")), 1);
- bool async_reset_pol = cell->parameters.at(RTLIL::IdString("\\ARST_POLARITY")).as_bool();
- int async_reset_value = dump_const(&cell->parameters.at(RTLIL::IdString("\\ARST_VALUE")),
- output_width, 0);
- ++line_num;
- str = stringf ("%d %s %d %s%d %d %d", line_num, cell_type_translation.at("$mux").c_str(),
- output_width, async_reset_pol ? "":"-", async_reset, async_reset_value, next);
- f << stringf("%s\n", str.c_str());
+ if (bit_cell.count(bit) == 0)
+ log_error("No driver for signal bit %s.\n", log_signal(bit));
+ export_cell(bit_cell.at(bit));
+ log_assert(bit_nid.count(bit));
}
- ++line_num;
- str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(),
- output_width, reg, next);
- f << stringf("%s\n", str.c_str());
}
- line_ref[cell->name]=line_num;
- }
- //memories
- else if(cell->type == "$memrd")
- {
- log("writing memrd cell\n");
- if (cell->parameters.at("\\CLK_ENABLE").as_bool() == true)
- log_error("The btor backen does not support $memrd cells with built-in registers. Run memory_dff with -wr_only.\n");
- str = cell->parameters.at(RTLIL::IdString("\\MEMID")).decode_string();
- int mem = dump_memory(module->memories.at(RTLIL::IdString(str.c_str())));
- int address_width = cell->parameters.at(RTLIL::IdString("\\ABITS")).as_int();
- int address = dump_sigspec(&cell->getPort(RTLIL::IdString("\\ADDR")), address_width);
- int data_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int();
- ++line_num;
- str = stringf("%d read %d %d %d", line_num, data_width, mem, address);
- f << stringf("%s\n", str.c_str());
- line_ref[cell->name]=line_num;
+
+ nidbits.push_back(bit_nid.at(bit));
}
- else if(cell->type == "$memwr")
+
+ int width = 0;
+ int nid = -1;
+
+ // group bits and emit slice-concat chain
+ for (int i = 0; i < GetSize(nidbits); i++)
{
- log("writing memwr cell\n");
- if (cell->parameters.at("\\CLK_ENABLE").as_bool() == false)
- log_error("The btor backen does not support $memwr cells without built-in registers. Run memory_dff (but with -wr_only).\n");
- int clk = dump_sigspec(&cell->getPort(RTLIL::IdString("\\CLK")), 1);
- bool polarity = cell->parameters.at(RTLIL::IdString("\\CLK_POLARITY")).as_bool();
- int enable = dump_sigspec(&cell->getPort(RTLIL::IdString("\\EN")), 1);
- int address_width = cell->parameters.at(RTLIL::IdString("\\ABITS")).as_int();
- int address = dump_sigspec(&cell->getPort(RTLIL::IdString("\\ADDR")), address_width);
- int data_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int();
- int data = dump_sigspec(&cell->getPort(RTLIL::IdString("\\DATA")), data_width);
- str = cell->parameters.at(RTLIL::IdString("\\MEMID")).decode_string();
- int mem = dump_memory(module->memories.at(RTLIL::IdString(str.c_str())));
- //check if the memory has already next
- /*
- auto it = mem_next.find(mem);
- if(it != std::end(mem_next))
- {
- ++line_num;
- str = cell->parameters.at(RTLIL::IdString("\\MEMID")).decode_string();
- RTLIL::Memory *memory = module->memories.at(RTLIL::IdString(str.c_str()));
- int address_bits = ceil_log2(memory->size);
- str = stringf("%d array %d %d", line_num, memory->width, address_bits);
- f << stringf("%s\n", str.c_str());
- ++line_num;
- str = stringf("%d eq 1 %d %d; mem invar", line_num, mem, line_num - 1);
- f << stringf("%s\n", str.c_str());
- mem = line_num - 1;
+ int nid2 = nidbits[i].first;
+ int lower = nidbits[i].second;
+ int upper = lower;
+
+ while (i+1 < GetSize(nidbits) && nidbits[i+1].first == nidbits[i].first &&
+ nidbits[i+1].second == nidbits[i].second+1)
+ upper++, i++;
+
+ int nid3 = nid2;
+
+ if (lower != 0 || upper+1 != nid_width.at(nid2)) {
+ int sid = get_bv_sid(upper-lower+1);
+ nid3 = next_nid++;
+ btorf("%d slice %d %d %d %d\n", nid3, sid, nid2, upper, lower);
}
- */
- ++line_num;
- if(polarity)
- str = stringf("%d one 1", line_num);
- else
- str = stringf("%d zero 1", line_num);
- f << stringf("%s\n", str.c_str());
- ++line_num;
- str = stringf("%d eq 1 %d %d", line_num, clk, line_num-1);
- f << stringf("%s\n", str.c_str());
- ++line_num;
- str = stringf("%d and 1 %d %d", line_num, line_num-1, enable);
- f << stringf("%s\n", str.c_str());
- ++line_num;
- str = stringf("%d write %d %d %d %d %d", line_num, data_width, address_width, mem, address, data);
- f << stringf("%s\n", str.c_str());
- /*
- ++line_num;
- str = stringf("%d acond %d %d %d %d %d", line_num, data_width, address_width, line_num-2, line_num-1, mem);
- f << stringf("%s\n", str.c_str());
- ++line_num;
- str = stringf("%d anext %d %d %d %d", line_num, data_width, address_width, mem, line_num-1);
- f << stringf("%s\n", str.c_str());
- */
- mem_next[mem].insert(std::make_pair(line_num-1, line_num));
+
+ int nid4 = nid3;
+
+ if (nid >= 0) {
+ int sid = get_bv_sid(width+upper-lower+1);
+ nid4 = next_nid++;
+ btorf("%d concat %d %d %d\n", nid4, sid, nid3, nid);
+ }
+
+ width += upper-lower+1;
+ nid = nid4;
}
- else if(cell->type == "$slice")
+
+ sig_nid[sig] = nid;
+ nid_width[nid] = width;
+ }
+
+ nid = sig_nid.at(sig);
+
+ extend_or_trim:
+ if (to_width >= 0 && to_width != GetSize(sig))
+ {
+ if (to_width < GetSize(sig))
{
- log("writing slice cell\n");
- const RTLIL::SigSpec* input = &cell->getPort(RTLIL::IdString("\\A"));
- int input_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int();
- log_assert(input->size() == input_width);
- int input_line = dump_sigspec(input, input_width);
- const RTLIL::SigSpec* output YS_ATTRIBUTE(unused) = &cell->getPort(RTLIL::IdString("\\Y"));
- int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int();
- log_assert(output->size() == output_width);
- int offset = cell->parameters.at(RTLIL::IdString("\\OFFSET")).as_int();
- ++line_num;
- str = stringf("%d %s %d %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(), output_width, input_line, output_width+offset-1, offset);
- f << stringf("%s\n", str.c_str());
- line_ref[cell->name]=line_num;
+ int sid = get_bv_sid(to_width);
+ int nid2 = next_nid++;
+ btorf("%d slice %d %d %d 0\n", nid2, sid, nid, to_width-1);
+ nid = nid2;
}
- else if(cell->type == "$concat")
+ else
{
- log("writing concat cell\n");
- const RTLIL::SigSpec* input_a = &cell->getPort(RTLIL::IdString("\\A"));
- int input_a_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int();
- log_assert(input_a->size() == input_a_width);
- int input_a_line = dump_sigspec(input_a, input_a_width);
- const RTLIL::SigSpec* input_b = &cell->getPort(RTLIL::IdString("\\B"));
- int input_b_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int();
- log_assert(input_b->size() == input_b_width);
- int input_b_line = dump_sigspec(input_b, input_b_width);
- ++line_num;
- str = stringf("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(), input_a_width+input_b_width,
- input_a_line, input_b_line);
- f << stringf("%s\n", str.c_str());
- line_ref[cell->name]=line_num;
+ int sid = get_bv_sid(to_width);
+ int nid2 = next_nid++;
+ btorf("%d %s %d %d %d\n", nid2, is_signed ? "sext" : "uext",
+ sid, nid, to_width - GetSize(sig));
+ nid = nid2;
}
- curr_cell.clear();
- return line_num;
- }
- else
- {
- return it->second;
}
+
+ return nid;
}
- const RTLIL::SigSpec* get_cell_output(RTLIL::Cell* cell)
+ BtorWorker(std::ostream &f, RTLIL::Module *module, bool verbose, bool single_bad) :
+ f(f), sigmap(module), module(module), verbose(verbose), single_bad(single_bad)
{
- const RTLIL::SigSpec *output_sig = nullptr;
- if (cell->type == "$memrd")
- {
- output_sig = &cell->getPort(RTLIL::IdString("\\DATA"));
- }
- else if(cell->type == "$memwr" || cell->type == "$assert")
+ btorf_push("inputs");
+
+ for (auto wire : module->wires())
{
- //no output
+ if (wire->attributes.count("\\init")) {
+ Const attrval = wire->attributes.at("\\init");
+ for (int i = 0; i < GetSize(wire) && i < GetSize(attrval); i++)
+ if (attrval[i] == State::S0 || attrval[i] == State::S1)
+ initbits[sigmap(SigBit(wire, i))] = (attrval[i] == State::S1);
+ }
+
+ if (!wire->port_id || !wire->port_input)
+ continue;
+
+ SigSpec sig = sigmap(wire);
+ int sid = get_bv_sid(GetSize(sig));
+ int nid = next_nid++;
+
+ btorf("%d input %d %s\n", nid, sid, log_id(wire));
+ add_nid_sig(nid, sig);
}
- else if(cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffsr")
+
+ btorf_pop("inputs");
+
+ for (auto cell : module->cells())
+ for (auto &conn : cell->connections())
{
- output_sig = &cell->getPort(RTLIL::IdString("\\Q"));
+ if (!cell->output(conn.first))
+ continue;
+
+ for (auto bit : sigmap(conn.second))
+ bit_cell[bit] = cell;
}
- else
+
+ for (auto wire : module->wires())
{
- output_sig = &cell->getPort(RTLIL::IdString("\\Y"));
- }
- return output_sig;
- }
+ if (!wire->port_id || !wire->port_output)
+ continue;
- void dump_property(RTLIL::Wire *wire)
- {
- int l = dump_wire(wire);
- ++line_num;
- str = stringf("%d root 1 %d", line_num, l);
- f << stringf("%s\n", str.c_str());
- }
+ btorf_push(stringf("output %s", log_id(wire)));
- void dump()
- {
- f << stringf(";module %s\n", cstr(module->name));
+ int sid = get_bv_sid(GetSize(wire));
+ int nid = get_sig_nid(wire);
+ btorf("%d output %d %d %s\n", next_nid++, sid, nid, log_id(wire));
+
+ btorf_pop(stringf("output %s", log_id(wire)));
+ }
- log("creating intermediate wires map\n");
- //creating map of intermediate wires as output of some cell
- for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it)
+ for (auto cell : module->cells())
{
- RTLIL::Cell *cell = it->second;
- const RTLIL::SigSpec* output_sig = get_cell_output(cell);
- if(output_sig==nullptr)
- continue;
- RTLIL::SigSpec s = sigmap(*output_sig);
- output_sig = &s;
- log(" - %s\n", cstr(it->second->type));
- if (cell->type == "$memrd")
- {
- for(unsigned i=0; i<output_sig->chunks().size(); ++i)
- {
- RTLIL::Wire *w = output_sig->chunks().at(i).wire;
- RTLIL::IdString wire_id = w->name;
- inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks().at(i)));
- }
- }
- else if(cell->type == "$memwr")
+ if (cell->type == "$assume")
{
- continue;//nothing to do
- }
- else if(cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffsr")
- {
- RTLIL::IdString wire_id = output_sig->chunks().front().wire->name;
- for(unsigned i=0; i<output_sig->chunks().size(); ++i)
- {
- RTLIL::Wire *w = output_sig->chunks().at(i).wire;
- RTLIL::IdString wire_id = w->name;
- inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks().at(i)));
- basic_wires[wire_id] = true;
- }
+ btorf_push(log_id(cell));
+
+ int sid = get_bv_sid(1);
+ int nid_a = get_sig_nid(cell->getPort("\\A"));
+ int nid_en = get_sig_nid(cell->getPort("\\EN"));
+ int nid_not_en = next_nid++;
+ int nid_a_or_not_en = next_nid++;
+ int nid = next_nid++;
+
+ btorf("%d not %d %d\n", nid_not_en, sid, nid_en);
+ btorf("%d or %d %d %d\n", nid_a_or_not_en, sid, nid_a, nid_not_en);
+ btorf("%d constraint %d\n", nid, nid_a_or_not_en);
+
+ btorf_pop(log_id(cell));
}
- else
+
+ if (cell->type == "$assert")
{
- for(unsigned i=0; i<output_sig->chunks().size(); ++i)
- {
- RTLIL::Wire *w = output_sig->chunks().at(i).wire;
- RTLIL::IdString wire_id = w->name;
- inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks().at(i)));
+ btorf_push(log_id(cell));
+
+ int sid = get_bv_sid(1);
+ int nid_a = get_sig_nid(cell->getPort("\\A"));
+ int nid_en = get_sig_nid(cell->getPort("\\EN"));
+ int nid_not_a = next_nid++;
+ int nid_en_and_not_a = next_nid++;
+
+ btorf("%d not %d %d\n", nid_not_a, sid, nid_a);
+ btorf("%d and %d %d %d\n", nid_en_and_not_a, sid, nid_en, nid_not_a);
+
+ if (single_bad) {
+ bad_properties.push_back(nid_en_and_not_a);
+ } else {
+ int nid = next_nid++;
+ btorf("%d bad %d\n", nid, nid_en_and_not_a);
}
- }
- }
- log("writing input\n");
- std::map<int, RTLIL::Wire*> inputs, outputs;
- std::vector<RTLIL::Wire*> safety;
-
- for (auto &wire_it : module->wires_) {
- RTLIL::Wire *wire = wire_it.second;
- if (wire->port_input)
- inputs[wire->port_id] = wire;
- if (wire->port_output) {
- outputs[wire->port_id] = wire;
- if (wire->name.str().find("safety") != std::string::npos )
- safety.push_back(wire);
+ btorf_pop(log_id(cell));
}
}
- f << stringf(";inputs\n");
- for (auto &it : inputs) {
- RTLIL::Wire *wire = it.second;
- dump_wire(wire);
+ for (auto wire : module->wires())
+ {
+ if (wire->port_id || wire->name[0] == '$')
+ continue;
+
+ btorf_push(stringf("wire %s", log_id(wire)));
+
+ int sid = get_bv_sid(GetSize(wire));
+ int nid = get_sig_nid(sigmap(wire));
+
+ if (statewires.count(wire))
+ continue;
+
+ int this_nid = next_nid++;
+ btorf("%d uext %d %d %d %s\n", this_nid, sid, nid, 0, log_id(wire));
+
+ btorf_pop(stringf("wire %s", log_id(wire)));
+ continue;
}
- f << stringf("\n");
- log("writing memories\n");
- for(auto mem_it = module->memories.begin(); mem_it != module->memories.end(); ++mem_it)
+ while (!ff_todo.empty())
{
- dump_memory(mem_it->second);
- }
+ vector<pair<int, Cell*>> todo;
+ todo.swap(ff_todo);
+
+ for (auto &it : todo)
+ {
+ int nid = it.first;
+ Cell *cell = it.second;
+
+ btorf_push(stringf("next %s", log_id(cell)));
+
+ if (cell->type == "$mem")
+ {
+ int abits = cell->getParam("\\ABITS").as_int();
+ int width = cell->getParam("\\WIDTH").as_int();
+ int wrports = cell->getParam("\\WR_PORTS").as_int();
+
+ SigSpec sig_wr_addr = sigmap(cell->getPort("\\WR_ADDR"));
+ SigSpec sig_wr_data = sigmap(cell->getPort("\\WR_DATA"));
+ SigSpec sig_wr_en = sigmap(cell->getPort("\\WR_EN"));
+
+ int data_sid = get_bv_sid(width);
+ int bool_sid = get_bv_sid(1);
+ int sid = get_mem_sid(abits, width);
+ int nid_head = nid;
+
+ for (int port = 0; port < wrports; port++)
+ {
+ SigSpec wa = sig_wr_addr.extract(port*abits, abits);
+ SigSpec wd = sig_wr_data.extract(port*width, width);
+ SigSpec we = sig_wr_en.extract(port*width, width);
+
+ int wa_nid = get_sig_nid(wa);
+ int wd_nid = get_sig_nid(wd);
+ int we_nid = get_sig_nid(we);
+
+ int nid2 = next_nid++;
+ btorf("%d read %d %d %d\n", nid2, data_sid, nid_head, wa_nid);
+
+ int nid3 = next_nid++;
+ btorf("%d not %d %d\n", nid3, data_sid, we_nid);
+
+ int nid4 = next_nid++;
+ btorf("%d and %d %d %d\n", nid4, data_sid, nid2, nid3);
+
+ int nid5 = next_nid++;
+ btorf("%d and %d %d %d\n", nid5, data_sid, wd_nid, we_nid);
+
+ int nid6 = next_nid++;
+ btorf("%d or %d %d %d\n", nid6, data_sid, nid5, nid4);
+
+ int nid7 = next_nid++;
+ btorf("%d write %d %d %d %d\n", nid7, sid, nid_head, wa_nid, nid6);
+
+ int nid8 = next_nid++;
+ btorf("%d redor %d %d\n", nid8, bool_sid, we_nid);
+
+ int nid9 = next_nid++;
+ btorf("%d ite %d %d %d %d\n", nid9, sid, nid8, nid7, nid_head);
+
+ nid_head = nid9;
+ }
+
+ int nid2 = next_nid++;
+ btorf("%d next %d %d %d\n", nid2, sid, nid, nid_head);
+ }
+ else
+ {
+ SigSpec sig = sigmap(cell->getPort("\\D"));
+ int nid_q = get_sig_nid(sig);
+ int sid = get_bv_sid(GetSize(sig));
+ btorf("%d next %d %d %d\n", next_nid++, sid, nid, nid_q);
+ }
- log("writing output wires\n");
- for (auto &it : outputs) {
- RTLIL::Wire *wire = it.second;
- dump_wire(wire);
+ btorf_pop(stringf("next %s", log_id(cell)));
+ }
}
- log("writing cells\n");
- for(auto cell_it = module->cells_.begin(); cell_it != module->cells_.end(); ++cell_it)
+ while (!bad_properties.empty())
{
- dump_cell(cell_it->second);
- }
+ vector<int> todo;
+ bad_properties.swap(todo);
- log("writing memory next");
- for(auto mem_it = module->memories.begin(); mem_it != module->memories.end(); ++mem_it)
- {
- dump_memory_next(mem_it->second);
- }
+ int sid = get_bv_sid(1);
+ int cursor = 0;
- for(auto it: safety)
- dump_property(it);
+ while (cursor+1 < GetSize(todo))
+ {
+ int nid_a = todo[cursor++];
+ int nid_b = todo[cursor++];
+ int nid = next_nid++;
- f << stringf("\n");
+ bad_properties.push_back(nid);
+ btorf("%d or %d %d %d\n", nid, sid, nid_a, nid_b);
+ }
- log("writing outputs info\n");
- f << stringf(";outputs\n");
- for (auto &it : outputs) {
- RTLIL::Wire *wire = it.second;
- int l = dump_wire(wire);
- f << stringf(";%d %s", l, cstr(wire->name));
+ if (!bad_properties.empty()) {
+ if (cursor < GetSize(todo))
+ bad_properties.push_back(todo[cursor++]);
+ log_assert(cursor == GetSize(todo));
+ } else {
+ int nid = next_nid++;
+ log_assert(cursor == 0);
+ log_assert(GetSize(todo) == 1);
+ btorf("%d bad %d\n", nid, todo[cursor]);
+ }
}
- f << stringf("\n");
- }
-
- static void dump(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, BtorDumperConfig &config)
- {
- BtorDumper dumper(f, module, design, &config);
- dumper.dump();
}
};
struct BtorBackend : public Backend {
BtorBackend() : Backend("btor", "write design to BTOR file") { }
-
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" write_btor [filename]\n");
+ log(" write_btor [options] [filename]\n");
+ log("\n");
+ log("Write a BTOR description of the current design.\n");
+ log("\n");
+ log(" -v\n");
+ log(" Add comments and indentation to BTOR output file\n");
+ log("\n");
+ log(" -s\n");
+ log(" Output only a single bad property for all asserts\n");
log("\n");
- log("Write the current design to an BTOR file.\n");
}
-
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
- std::string top_module_name;
- std::string buf_type, buf_in, buf_out;
- std::string true_type, true_out;
- std::string false_type, false_out;
- BtorDumperConfig config;
+ bool verbose = false, single_bad = false;
log_header(design, "Executing BTOR backend.\n");
- size_t argidx=1;
- extra_args(f, filename, args, argidx);
-
- if (top_module_name.empty())
- for (auto & mod_it:design->modules_)
- if (mod_it.second->get_bool_attribute("\\top"))
- top_module_name = mod_it.first.str();
-
- *f << stringf("; Generated by %s\n", yosys_version_str);
- *f << stringf("; %s developed and maintained by Clifford Wolf <clifford@clifford.at>\n", yosys_version_str);
- *f << stringf("; BTOR Backend developed by Ahmed Irfan <irfan@fbk.eu> - Fondazione Bruno Kessler, Trento, Italy\n");
- *f << stringf(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n");
-
- std::vector<RTLIL::Module*> mod_list;
-
- for (auto module_it : design->modules_)
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
{
- RTLIL::Module *module = module_it.second;
- if (module->get_bool_attribute("\\blackbox"))
+ if (args[argidx] == "-v") {
+ verbose = true;
continue;
-
- if (module->processes.size() != 0)
- log_error("Found unmapped processes in module %s: unmapped processes are not supported in BTOR backend!\n", RTLIL::id2cstr(module->name));
-
- if (module->name == RTLIL::escape_id(top_module_name)) {
- BtorDumper::dump(*f, module, design, config);
- top_module_name.clear();
+ }
+ if (args[argidx] == "-s") {
+ single_bad = true;
continue;
}
-
- mod_list.push_back(module);
+ break;
}
+ extra_args(f, filename, args, argidx);
+
+ RTLIL::Module *topmod = design->top_module();
+
+ if (topmod == nullptr)
+ log_cmd_error("No top module found.\n");
+
+ *f << stringf("; BTOR description generated by %s for module %s.\n",
+ yosys_version_str, log_id(topmod));
- if (!top_module_name.empty())
- log_error("Can't find top module `%s'!\n", top_module_name.c_str());
+ BtorWorker(*f, topmod, verbose, single_bad);
- for (auto module : mod_list)
- BtorDumper::dump(*f, module, design, config);
+ *f << stringf("; end of yosys output\n");
}
} BtorBackend;
diff --git a/backends/btor/test_cells.sh b/backends/btor/test_cells.sh
new file mode 100644
index 00000000..e0f1a051
--- /dev/null
+++ b/backends/btor/test_cells.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+set -ex
+
+rm -rf test_cells.tmp
+mkdir -p test_cells.tmp
+cd test_cells.tmp
+
+../../../yosys -p 'test_cell -n 5 -w test all /$alu /$fa /$lcu /$lut /$sop /$macc /$mul /$div /$mod'
+
+for fn in test_*.il; do
+ ../../../yosys -p "
+ read_ilang $fn
+ rename gold gate
+ synth
+
+ read_ilang $fn
+ miter -equiv -make_assert -flatten gold gate main
+ hierarchy -top main
+ write_btor ${fn%.il}.btor
+ "
+ boolectormc -kmax 1 --trace-gen --stop-first -v ${fn%.il}.btor > ${fn%.il}.out
+ if grep " SATISFIABLE" ${fn%.il}.out; then
+ echo "Check failed for ${fn%.il}."
+ exit 1
+ fi
+done
+
+echo "OK."
+
diff --git a/backends/btor/verilog2btor.sh b/backends/btor/verilog2btor.sh
deleted file mode 100755
index dfd7f1a8..00000000
--- a/backends/btor/verilog2btor.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/sh
-
-#
-# Script to write BTOR from Verilog design
-#
-
-if [ "$#" -ne 3 ]; then
- echo "Usage: $0 input.v output.btor top-module-name" >&2
- exit 1
-fi
-if ! [ -e "$1" ]; then
- echo "$1 not found" >&2
- exit 1
-fi
-
-FULL_PATH=$(readlink -f $1)
-DIR=$(dirname $FULL_PATH)
-
-./yosys -q -p "
-read_verilog -sv $1;
-hierarchy -top $3;
-hierarchy -libdir $DIR;
-hierarchy -check;
-proc;
-opt; opt_expr -mux_undef; opt;
-rename -hide;;;
-#techmap -map +/pmux2mux.v;;
-splice; opt;
-memory_dff -wr_only;
-memory_collect;;
-flatten;;
-memory_unpack;
-splitnets -driver;
-setundef -zero -undriven;
-opt;;;
-write_btor $2;"
-
diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc
index d16f1831..5f9ec54f 100644
--- a/backends/edif/edif.cc
+++ b/backends/edif/edif.cc
@@ -31,65 +31,66 @@ USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
#define EDIF_DEF(_id) edif_names(RTLIL::unescape_id(_id), true).c_str()
+#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(RTLIL::unescape_id(_id), true, _ren, _bl, _br).c_str()
#define EDIF_REF(_id) edif_names(RTLIL::unescape_id(_id), false).c_str()
-namespace
+struct EdifNames
{
- struct EdifNames
- {
- int counter;
- std::set<std::string> generated_names, used_names;
- std::map<std::string, std::string> name_map;
+ int counter;
+ char delim_left, delim_right;
+ std::set<std::string> generated_names, used_names;
+ std::map<std::string, std::string> name_map;
- EdifNames() : counter(1) { }
+ EdifNames() : counter(1), delim_left('['), delim_right(']') { }
- std::string operator()(std::string id, bool define)
- {
- if (define) {
- std::string new_id = operator()(id, false);
- return new_id != id ? stringf("(rename %s \"%s\")", new_id.c_str(), id.c_str()) : id;
- }
+ std::string operator()(std::string id, bool define, bool port_rename = false, int range_left = 0, int range_right = 0)
+ {
+ if (define) {
+ std::string new_id = operator()(id, false);
+ if (port_rename)
+ return stringf("(rename %s \"%s%c%d:%d%c\")", new_id.c_str(), id.c_str(), delim_left, range_left, range_right, delim_right);
+ return new_id != id ? stringf("(rename %s \"%s\")", new_id.c_str(), id.c_str()) : id;
+ }
- if (name_map.count(id) > 0)
- return name_map.at(id);
- if (generated_names.count(id) > 0)
- goto do_rename;
- if (id == "GND" || id == "VCC")
- goto do_rename;
+ if (name_map.count(id) > 0)
+ return name_map.at(id);
+ if (generated_names.count(id) > 0)
+ goto do_rename;
+ if (id == "GND" || id == "VCC")
+ goto do_rename;
- for (size_t i = 0; i < id.size(); i++) {
- if ('A' <= id[i] && id[i] <= 'Z')
- continue;
- if ('a' <= id[i] && id[i] <= 'z')
- continue;
- if ('0' <= id[i] && id[i] <= '9' && i > 0)
- continue;
- if (id[i] == '_' && i > 0 && i != id.size()-1)
- continue;
- goto do_rename;
- }
+ for (size_t i = 0; i < id.size(); i++) {
+ if ('A' <= id[i] && id[i] <= 'Z')
+ continue;
+ if ('a' <= id[i] && id[i] <= 'z')
+ continue;
+ if ('0' <= id[i] && id[i] <= '9' && i > 0)
+ continue;
+ if (id[i] == '_' && i > 0 && i != id.size()-1)
+ continue;
+ goto do_rename;
+ }
- used_names.insert(id);
- return id;
+ used_names.insert(id);
+ return id;
- do_rename:;
- std::string gen_name;
- while (1) {
- gen_name = stringf("id%05d", counter++);
- if (generated_names.count(gen_name) == 0 &&
- used_names.count(gen_name) == 0)
- break;
- }
- generated_names.insert(gen_name);
- name_map[id] = gen_name;
- return gen_name;
+ do_rename:;
+ std::string gen_name;
+ while (1) {
+ gen_name = stringf("id%05d", counter++);
+ if (generated_names.count(gen_name) == 0 &&
+ used_names.count(gen_name) == 0)
+ break;
}
- };
-}
+ generated_names.insert(gen_name);
+ name_map[id] = gen_name;
+ return gen_name;
+ }
+};
struct EdifBackend : public Backend {
EdifBackend() : Backend("edif", "write design to EDIF netlist file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -105,17 +106,21 @@ struct EdifBackend : public Backend {
log(" if the design contains constant nets. use \"hilomap\" to map to custom\n");
log(" constant drivers first)\n");
log("\n");
+ log(" -pvector {par|bra|ang}\n");
+ log(" sets the delimiting character for module port rename clauses to\n");
+ log(" parentheses, square brackets, or angle brackets.\n");
+ log("\n");
log("Unfortunately there are different \"flavors\" of the EDIF file format. This\n");
log("command generates EDIF files for the Xilinx place&route tools. It might be\n");
log("necessary to make small modifications to this command when a different tool\n");
log("is targeted.\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing EDIF backend.\n");
-
std::string top_module_name;
+ bool port_rename = false;
std::map<RTLIL::IdString, std::map<RTLIL::IdString, int>> lib_cell_ports;
bool nogndvcc = false;
CellTypes ct(design);
@@ -132,6 +137,19 @@ struct EdifBackend : public Backend {
nogndvcc = true;
continue;
}
+ if (args[argidx] == "-pvector" && argidx+1 < args.size()) {
+ std::string parray;
+ port_rename = true;
+ parray = args[++argidx];
+ if (parray == "par") {
+ edif_names.delim_left = '(';edif_names.delim_right = ')';
+ } else if (parray == "ang") {
+ edif_names.delim_left = '<';edif_names.delim_right = '>';
+ } else {
+ edif_names.delim_left = '[';edif_names.delim_right = ']';
+ }
+ continue;
+ }
break;
}
extra_args(f, filename, args, argidx);
@@ -214,8 +232,18 @@ struct EdifBackend : public Backend {
}
if (port_it.second == 1)
*f << stringf(" (port %s (direction %s))\n", EDIF_DEF(port_it.first), dir);
- else
- *f << stringf(" (port (array %s %d) (direction %s))\n", EDIF_DEF(port_it.first), port_it.second, dir);
+ else {
+ int b[2] = {port_it.second-1, 0};
+ auto m = design->module(cell_it.first);
+ if (m) {
+ auto w = m->wire(port_it.first);
+ if (w) {
+ b[w->upto ? 0 : 1] = w->start_offset;
+ b[w->upto ? 1 : 0] = w->start_offset+GetSize(w)-1;
+ }
+ }
+ *f << stringf(" (port (array %s %d) (direction %s))\n", EDIF_DEFR(port_it.first, port_rename, b[0], b[1]), port_it.second, dir);
+ }
}
*f << stringf(" )\n");
*f << stringf(" )\n");
@@ -283,10 +311,13 @@ struct EdifBackend : public Backend {
RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire));
net_join_db[sig].insert(stringf("(portRef %s)", EDIF_REF(wire->name)));
} else {
- *f << stringf(" (port (array %s %d) (direction %s))\n", EDIF_DEF(wire->name), wire->width, dir);
+ int b[2];
+ b[wire->upto ? 0 : 1] = wire->start_offset;
+ b[wire->upto ? 1 : 0] = wire->start_offset + GetSize(wire) - 1;
+ *f << stringf(" (port (array %s %d) (direction %s))\n", EDIF_DEFR(wire->name, port_rename, b[0], b[1]), wire->width, dir);
for (int i = 0; i < wire->width; i++) {
RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire, i));
- net_join_db[sig].insert(stringf("(portRef (member %s %d))", EDIF_REF(wire->name), i));
+ net_join_db[sig].insert(stringf("(portRef (member %s %d))", EDIF_REF(wire->name), GetSize(wire)-i-1));
}
}
}
@@ -323,20 +354,48 @@ struct EdifBackend : public Backend {
for (auto &p : cell->connections()) {
RTLIL::SigSpec sig = sigmap(p.second);
for (int i = 0; i < GetSize(sig); i++)
- if (sig.size() == 1)
+ if (sig[i].wire == NULL && sig[i] != RTLIL::State::S0 && sig[i] != RTLIL::State::S1)
+ log_warning("Bit %d of cell port %s.%s.%s driven by %s will be left unconnected in EDIF output.\n",
+ i, log_id(module), log_id(cell), log_id(p.first), log_signal(sig[i]));
+ else if (sig.size() == 1)
net_join_db[sig[i]].insert(stringf("(portRef %s (instanceRef %s))", EDIF_REF(p.first), EDIF_REF(cell->name)));
- else
- net_join_db[sig[i]].insert(stringf("(portRef (member %s %d) (instanceRef %s))", EDIF_REF(p.first), i, EDIF_REF(cell->name)));
+ else {
+ int member_idx = GetSize(sig)-i-1;
+ auto m = design->module(cell->type);
+ if (m) {
+ auto w = m->wire(p.first);
+ if (w)
+ member_idx = GetSize(w)-i-1;
+ }
+ net_join_db[sig[i]].insert(stringf("(portRef (member %s %d) (instanceRef %s))",
+ EDIF_REF(p.first), member_idx, EDIF_REF(cell->name)));
+ }
}
}
for (auto &it : net_join_db) {
RTLIL::SigBit sig = it.first;
- if (sig.wire == NULL && sig != RTLIL::State::S0 && sig != RTLIL::State::S1)
- continue;
- std::string netname = log_signal(sig);
- for (size_t i = 0; i < netname.size(); i++)
- if (netname[i] == ' ' || netname[i] == '\\')
- netname.erase(netname.begin() + i--);
+ if (sig.wire == NULL && sig != RTLIL::State::S0 && sig != RTLIL::State::S1) {
+ if (sig == RTLIL::State::Sx) {
+ for (auto &ref : it.second)
+ log_warning("Exporting x-bit on %s as zero bit.\n", ref.c_str());
+ sig = RTLIL::State::S0;
+ } else {
+ for (auto &ref : it.second)
+ log_error("Don't know how to handle %s on %s.\n", log_signal(sig), ref.c_str());
+ log_abort();
+ }
+ }
+ std::string netname;
+ if (sig == RTLIL::State::S0)
+ netname = "GND_NET";
+ else if (sig == RTLIL::State::S1)
+ netname = "VCC_NET";
+ else {
+ netname = log_signal(sig);
+ for (size_t i = 0; i < netname.size(); i++)
+ if (netname[i] == ' ' || netname[i] == '\\')
+ netname.erase(netname.begin() + i--);
+ }
*f << stringf(" (net %s (joined\n", EDIF_DEF(netname));
for (auto &ref : it.second)
*f << stringf(" %s\n", ref.c_str());
diff --git a/backends/edif/runtest.py b/backends/edif/runtest.py
new file mode 100644
index 00000000..826876a8
--- /dev/null
+++ b/backends/edif/runtest.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python3
+
+import os
+import numpy as np
+
+enable_upto = True
+enable_offset = True
+enable_hierarchy = True
+enable_logic = True
+
+def make_module(f, modname, width, subs):
+ print("module %s (A, B, C, X, Y, Z);" % modname, file=f)
+ inbits = list()
+ outbits = list()
+
+ for p in "ABC":
+ offset = np.random.randint(10) if enable_offset else 0
+ if enable_upto and np.random.randint(2):
+ print(" input [%d:%d] %s;" % (offset, offset+width-1, p), file=f)
+ else:
+ print(" input [%d:%d] %s;" % (offset+width-1, offset, p), file=f)
+ for i in range(offset, offset+width):
+ inbits.append("%s[%d]" % (p, i))
+
+ for p in "XYZ":
+ offset = np.random.randint(10) if enable_offset else 0
+ if enable_upto and np.random.randint(2):
+ print(" output [%d:%d] %s;" % (offset, offset+width-1, p), file=f)
+ else:
+ print(" output [%d:%d] %s;" % (offset+width-1, offset, p), file=f)
+ for i in range(offset, offset+width):
+ outbits.append("%s[%d]" % (p, i))
+
+ instidx = 0
+ subcandidates = list(subs.keys())
+
+ while len(outbits) > 0:
+ submod = None
+ if len(subcandidates):
+ submod = np.random.choice(subcandidates)
+ subcandidates.remove(submod)
+
+ if submod is None or 3*subs[submod] >= len(outbits):
+ for bit in outbits:
+ if enable_logic:
+ print(" assign %s = %s & ~%s;" % (bit, np.random.choice(inbits), np.random.choice(inbits)), file=f)
+ else:
+ print(" assign %s = %s;" % (bit, np.random.choice(inbits)), file=f)
+ break
+
+ instidx += 1
+ print(" %s inst%d (" % (submod, instidx), file=f)
+
+ for p in "ABC":
+ print(" .%s({%s})," % (p, ",".join(np.random.choice(inbits, subs[submod]))), file=f)
+
+ for p in "XYZ":
+ bits = list(np.random.choice(outbits, subs[submod], False))
+ for bit in bits:
+ outbits.remove(bit)
+ print(" .%s({%s})%s" % (p, ",".join(bits), "," if p != "Z" else ""), file=f)
+
+ print(" );", file=f);
+
+ print("endmodule", file=f)
+
+with open("test_top.v", "w") as f:
+ if enable_hierarchy:
+ make_module(f, "sub1", 2, {})
+ make_module(f, "sub2", 3, {})
+ make_module(f, "sub3", 4, {})
+ make_module(f, "sub4", 8, {"sub1": 2, "sub2": 3, "sub3": 4})
+ make_module(f, "sub5", 8, {"sub1": 2, "sub2": 3, "sub3": 4})
+ make_module(f, "sub6", 8, {"sub1": 2, "sub2": 3, "sub3": 4})
+ make_module(f, "top", 32, {"sub4": 8, "sub5": 8, "sub6": 8})
+ else:
+ make_module(f, "top", 32, {})
+
+os.system("set -x; ../../yosys -p 'synth_xilinx -top top; write_edif -pvector par test_syn.edif' test_top.v")
+
+with open("test_syn.tcl", "w") as f:
+ print("read_edif test_syn.edif", file=f)
+ print("link_design", file=f)
+ print("write_verilog -force test_syn.v", file=f)
+
+os.system("set -x; vivado -nojournal -nolog -mode batch -source test_syn.tcl")
+
+with open("test_tb.v", "w") as f:
+ print("module tb;", file=f)
+ print(" reg [31:0] A, B, C;", file=f)
+ print(" wire [31:0] X, Y, Z;", file=f)
+ print("", file=f)
+ print(" top uut (", file=f)
+ print(" .A(A),", file=f)
+ print(" .B(B),", file=f)
+ print(" .C(C),", file=f)
+ print(" .X(X),", file=f)
+ print(" .Y(Y),", file=f)
+ print(" .Z(Z)", file=f)
+ print(" );", file=f)
+ print("", file=f)
+ print(" initial begin", file=f)
+ for i in range(100):
+ print(" A = 32'h%08x;" % np.random.randint(2**32), file=f)
+ print(" B = 32'h%08x;" % np.random.randint(2**32), file=f)
+ print(" C = 32'h%08x;" % np.random.randint(2**32), file=f)
+ print(" #10;", file=f)
+ print(" $display(\"%x %x %x\", X, Y, Z);", file=f)
+ print(" #10;", file=f)
+ print(" $finish;", file=f)
+ print(" end", file=f)
+ print("endmodule", file=f)
+
+os.system("set -x; iverilog -o test_gold test_tb.v test_top.v")
+os.system("set -x; iverilog -o test_gate test_tb.v test_syn.v ../../techlibs/xilinx/cells_sim.v")
+
+os.system("set -x; ./test_gold > test_gold.out")
+os.system("set -x; ./test_gate > test_gate.out")
+
+os.system("set -x; md5sum test_gold.out test_gate.out")
+
diff --git a/backends/firrtl/.gitignore b/backends/firrtl/.gitignore
new file mode 100644
index 00000000..a2ac93ab
--- /dev/null
+++ b/backends/firrtl/.gitignore
@@ -0,0 +1,2 @@
+test.fir
+test_out.v
diff --git a/backends/firrtl/Makefile.inc b/backends/firrtl/Makefile.inc
new file mode 100644
index 00000000..fdf100d3
--- /dev/null
+++ b/backends/firrtl/Makefile.inc
@@ -0,0 +1,3 @@
+
+OBJS += backends/firrtl/firrtl.o
+
diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc
new file mode 100644
index 00000000..94236d0b
--- /dev/null
+++ b/backends/firrtl/firrtl.cc
@@ -0,0 +1,677 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/rtlil.h"
+#include "kernel/register.h"
+#include "kernel/sigtools.h"
+#include "kernel/celltypes.h"
+#include "kernel/cellaigs.h"
+#include "kernel/log.h"
+#include <string>
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+pool<string> used_names;
+dict<IdString, string> namecache;
+int autoid_counter;
+
+typedef unsigned FDirection;
+static const FDirection NODIRECTION = 0x0;
+static const FDirection IN = 0x1;
+static const FDirection OUT = 0x2;
+static const FDirection INOUT = 0x3;
+
+// Get a port direction with respect to a specific module.
+FDirection getPortFDirection(IdString id, Module *module)
+{
+ Wire *wire = module->wires_.at(id);
+ FDirection direction = NODIRECTION;
+ if (wire && wire->port_id)
+ {
+ if (wire->port_input)
+ direction |= IN;
+ if (wire->port_output)
+ direction |= OUT;
+ }
+ return direction;
+}
+
+string next_id()
+{
+ string new_id;
+
+ while (1) {
+ new_id = stringf("_%d", autoid_counter++);
+ if (used_names.count(new_id) == 0) break;
+ }
+
+ used_names.insert(new_id);
+ return new_id;
+}
+
+const char *make_id(IdString id)
+{
+ if (namecache.count(id) != 0)
+ return namecache.at(id).c_str();
+
+ string new_id = log_id(id);
+
+ for (int i = 0; i < GetSize(new_id); i++)
+ {
+ char &ch = new_id[i];
+ if ('a' <= ch && ch <= 'z') continue;
+ if ('A' <= ch && ch <= 'Z') continue;
+ if ('0' <= ch && ch <= '9' && i != 0) continue;
+ if ('_' == ch) continue;
+ ch = '_';
+ }
+
+ while (used_names.count(new_id) != 0)
+ new_id += '_';
+
+ namecache[id] = new_id;
+ used_names.insert(new_id);
+ return namecache.at(id).c_str();
+}
+
+struct FirrtlWorker
+{
+ Module *module;
+ std::ostream &f;
+
+ dict<SigBit, pair<string, int>> reverse_wire_map;
+ string unconn_id;
+ RTLIL::Design *design;
+ std::string indent;
+
+ void register_reverse_wire_map(string id, SigSpec sig)
+ {
+ for (int i = 0; i < GetSize(sig); i++)
+ reverse_wire_map[sig[i]] = make_pair(id, i);
+ }
+
+ FirrtlWorker(Module *module, std::ostream &f, RTLIL::Design *theDesign) : module(module), f(f), design(theDesign), indent(" ")
+ {
+ }
+
+ string make_expr(const SigSpec &sig)
+ {
+ string expr;
+
+ for (auto chunk : sig.chunks())
+ {
+ string new_expr;
+
+ if (chunk.wire == nullptr)
+ {
+ std::vector<RTLIL::State> bits = chunk.data;
+ new_expr = stringf("UInt<%d>(\"h", GetSize(bits));
+
+ while (GetSize(bits) % 4 != 0)
+ bits.push_back(State::S0);
+
+ for (int i = GetSize(bits)-4; i >= 0; i -= 4)
+ {
+ int val = 0;
+ if (bits[i+0] == State::S1) val += 1;
+ if (bits[i+1] == State::S1) val += 2;
+ if (bits[i+2] == State::S1) val += 4;
+ if (bits[i+3] == State::S1) val += 8;
+ new_expr.push_back(val < 10 ? '0' + val : 'a' + val - 10);
+ }
+
+ new_expr += "\")";
+ }
+ else if (chunk.offset == 0 && chunk.width == chunk.wire->width)
+ {
+ new_expr = make_id(chunk.wire->name);
+ }
+ else
+ {
+ string wire_id = make_id(chunk.wire->name);
+ new_expr = stringf("bits(%s, %d, %d)", wire_id.c_str(), chunk.offset + chunk.width - 1, chunk.offset);
+ }
+
+ if (expr.empty())
+ expr = new_expr;
+ else
+ expr = "cat(" + new_expr + ", " + expr + ")";
+ }
+
+ return expr;
+ }
+
+ std::string fid(RTLIL::IdString internal_id)
+ {
+ const char *str = internal_id.c_str();
+ return *str == '\\' ? str + 1 : str;
+ }
+
+
+ std::string cellname(RTLIL::Cell *cell)
+ {
+ return fid(cell->name).c_str();
+ }
+
+ void process_instance(RTLIL::Cell *cell, vector<string> &wire_exprs)
+ {
+ std::string cell_type = fid(cell->type);
+
+ std::string cell_name = cellname(cell);
+ std::string cell_name_comment;
+ if (cell_name != fid(cell->name))
+ cell_name_comment = " /* " + fid(cell->name) + " */ ";
+ else
+ cell_name_comment = "";
+ // Find the module corresponding to this instance.
+ auto instModule = design->module(cell->type);
+ wire_exprs.push_back(stringf("%s" "inst %s%s of %s", indent.c_str(), cell_name.c_str(), cell_name_comment.c_str(), cell_type.c_str()));
+
+ for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) {
+ if (it->second.size() > 0) {
+ const SigSpec &secondSig = it->second;
+ const std::string firstName = cell_name + "." + make_id(it->first);
+ const std::string secondName = make_expr(secondSig);
+ // Find the direction for this port.
+ FDirection dir = getPortFDirection(it->first, instModule);
+ std::string source, sink;
+ switch (dir) {
+ case INOUT:
+ log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", log_id(cell_type), log_signal(it->second));
+ case OUT:
+ source = firstName;
+ sink = secondName;
+ break;
+ case NODIRECTION:
+ log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", log_id(cell_type), log_signal(it->second));
+ /* FALL_THROUGH */
+ case IN:
+ source = secondName;
+ sink = firstName;
+ break;
+ default:
+ log_error("Instance port %s.%s unrecognized connection direction 0x%x !\n", log_id(cell_type), log_signal(it->second), dir);
+ break;
+ }
+ wire_exprs.push_back(stringf("\n%s%s <= %s", indent.c_str(), sink.c_str(), source.c_str()));
+ }
+ }
+ wire_exprs.push_back(stringf("\n"));
+
+ }
+
+ void run()
+ {
+ f << stringf(" module %s:\n", make_id(module->name));
+ vector<string> port_decls, wire_decls, cell_exprs, wire_exprs;
+
+ for (auto wire : module->wires())
+ {
+ const auto wireName = make_id(wire->name);
+ if (wire->port_id)
+ {
+ if (wire->port_input && wire->port_output)
+ log_error("Module port %s.%s is inout!\n", log_id(module), log_id(wire));
+ port_decls.push_back(stringf(" %s %s: UInt<%d>\n", wire->port_input ? "input" : "output",
+ wireName, wire->width));
+ }
+ else
+ {
+ wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", wireName, wire->width));
+ }
+ }
+
+ for (auto cell : module->cells())
+ {
+ // Is this cell is a module instance?
+ if (cell->type[0] != '$')
+ {
+ process_instance(cell, wire_exprs);
+ continue;
+ }
+ if (cell->type.in("$not", "$logic_not", "$neg", "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_bool", "$reduce_xnor"))
+ {
+ string y_id = make_id(cell->name);
+ bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
+ int y_width = cell->parameters.at("\\Y_WIDTH").as_int();
+ string a_expr = make_expr(cell->getPort("\\A"));
+ wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
+
+ if (cell->parameters.at("\\A_SIGNED").as_bool()) {
+ a_expr = "asSInt(" + a_expr + ")";
+ }
+
+ // Don't use the results of logical operations (a single bit) to control padding
+ if (!(cell->type.in("$eq", "$eqx", "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$reduce_bool", "$logic_not") && y_width == 1) ) {
+ a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
+ }
+
+ string primop;
+ bool always_uint = false;
+ if (cell->type == "$not") primop = "not";
+ if (cell->type == "$neg") primop = "neg";
+ if (cell->type == "$logic_not") {
+ primop = "eq";
+ a_expr = stringf("%s, UInt(0)", a_expr.c_str());
+ }
+ if (cell->type == "$reduce_and") primop = "andr";
+ if (cell->type == "$reduce_or") primop = "orr";
+ if (cell->type == "$reduce_xor") primop = "xorr";
+ if (cell->type == "$reduce_xnor") {
+ primop = "not";
+ a_expr = stringf("xorr(%s)", a_expr.c_str());
+ }
+ if (cell->type == "$reduce_bool") {
+ primop = "neq";
+ // Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand.
+ bool a_signed = cell->parameters.at("\\A_SIGNED").as_bool();
+ int a_width = cell->parameters.at("\\A_WIDTH").as_int();
+ a_expr = stringf("%s, %cInt<%d>(0)", a_expr.c_str(), a_signed ? 'S' : 'U', a_width);
+ }
+
+ string expr = stringf("%s(%s)", primop.c_str(), a_expr.c_str());
+
+ if ((is_signed && !always_uint))
+ expr = stringf("asUInt(%s)", expr.c_str());
+
+ cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
+ register_reverse_wire_map(y_id, cell->getPort("\\Y"));
+
+ continue;
+ }
+ if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$and", "$or", "$eq", "$eqx",
+ "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl",
+ "$logic_and", "$logic_or"))
+ {
+ string y_id = make_id(cell->name);
+ bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
+ int y_width = cell->parameters.at("\\Y_WIDTH").as_int();
+ string a_expr = make_expr(cell->getPort("\\A"));
+ string b_expr = make_expr(cell->getPort("\\B"));
+ wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
+
+ if (cell->parameters.at("\\A_SIGNED").as_bool()) {
+ a_expr = "asSInt(" + a_expr + ")";
+ }
+ // Shift amount is always unsigned, and needn't be padded to result width.
+ if (!cell->type.in("$shr", "$sshr", "$shl", "$sshl")) {
+ if (cell->parameters.at("\\B_SIGNED").as_bool()) {
+ b_expr = "asSInt(" + b_expr + ")";
+ }
+ b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width);
+ }
+
+ a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width);
+
+ if (cell->parameters.at("\\A_SIGNED").as_bool() & (cell->type == "$shr")) {
+ a_expr = "asUInt(" + a_expr + ")";
+ }
+
+ string primop;
+ bool always_uint = false;
+ if (cell->type == "$add") primop = "add";
+ if (cell->type == "$sub") primop = "sub";
+ if (cell->type == "$mul") primop = "mul";
+ if (cell->type == "$div") primop = "div";
+ if (cell->type == "$mod") primop = "rem";
+ if (cell->type == "$and") {
+ primop = "and";
+ always_uint = true;
+ }
+ if (cell->type == "$or" ) {
+ primop = "or";
+ always_uint = true;
+ }
+ if (cell->type == "$xor") {
+ primop = "xor";
+ always_uint = true;
+ }
+ if ((cell->type == "$eq") | (cell->type == "$eqx")) {
+ primop = "eq";
+ always_uint = true;
+ }
+ if ((cell->type == "$ne") | (cell->type == "$nex")) {
+ primop = "neq";
+ always_uint = true;
+ }
+ if (cell->type == "$gt") {
+ primop = "gt";
+ always_uint = true;
+ }
+ if (cell->type == "$ge") {
+ primop = "geq";
+ always_uint = true;
+ }
+ if (cell->type == "$lt") {
+ primop = "lt";
+ always_uint = true;
+ }
+ if (cell->type == "$le") {
+ primop = "leq";
+ always_uint = true;
+ }
+ if ((cell->type == "$shl") | (cell->type == "$sshl")) primop = "dshl";
+ if ((cell->type == "$shr") | (cell->type == "$sshr")) primop = "dshr";
+ if ((cell->type == "$logic_and")) {
+ primop = "and";
+ a_expr = "neq(" + a_expr + ", UInt(0))";
+ b_expr = "neq(" + b_expr + ", UInt(0))";
+ always_uint = true;
+ }
+ if ((cell->type == "$logic_or")) {
+ primop = "or";
+ a_expr = "neq(" + a_expr + ", UInt(0))";
+ b_expr = "neq(" + b_expr + ", UInt(0))";
+ always_uint = true;
+ }
+
+ if (!cell->parameters.at("\\B_SIGNED").as_bool()) {
+ b_expr = "asUInt(" + b_expr + ")";
+ }
+
+ string expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str());
+
+ if ((is_signed && !always_uint) || cell->type.in("$sub"))
+ expr = stringf("asUInt(%s)", expr.c_str());
+
+ cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
+ register_reverse_wire_map(y_id, cell->getPort("\\Y"));
+
+ continue;
+ }
+
+ if (cell->type.in("$mux"))
+ {
+ string y_id = make_id(cell->name);
+ int width = cell->parameters.at("\\WIDTH").as_int();
+ string a_expr = make_expr(cell->getPort("\\A"));
+ string b_expr = make_expr(cell->getPort("\\B"));
+ string s_expr = make_expr(cell->getPort("\\S"));
+ wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), width));
+
+ string expr = stringf("mux(%s, %s, %s)", s_expr.c_str(), b_expr.c_str(), a_expr.c_str());
+
+ cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
+ register_reverse_wire_map(y_id, cell->getPort("\\Y"));
+
+ continue;
+ }
+
+ if (cell->type.in("$mem"))
+ {
+ string mem_id = make_id(cell->name);
+ int abits = cell->parameters.at("\\ABITS").as_int();
+ int width = cell->parameters.at("\\WIDTH").as_int();
+ int size = cell->parameters.at("\\SIZE").as_int();
+ int rd_ports = cell->parameters.at("\\RD_PORTS").as_int();
+ int wr_ports = cell->parameters.at("\\WR_PORTS").as_int();
+
+ Const initdata = cell->parameters.at("\\INIT");
+ for (State bit : initdata.bits)
+ if (bit != State::Sx)
+ log_error("Memory with initialization data: %s.%s\n", log_id(module), log_id(cell));
+
+ Const rd_clk_enable = cell->parameters.at("\\RD_CLK_ENABLE");
+ Const wr_clk_enable = cell->parameters.at("\\WR_CLK_ENABLE");
+ Const wr_clk_polarity = cell->parameters.at("\\WR_CLK_POLARITY");
+
+ int offset = cell->parameters.at("\\OFFSET").as_int();
+ if (offset != 0)
+ log_error("Memory with nonzero offset: %s.%s\n", log_id(module), log_id(cell));
+
+ cell_exprs.push_back(stringf(" mem %s:\n", mem_id.c_str()));
+ cell_exprs.push_back(stringf(" data-type => UInt<%d>\n", width));
+ cell_exprs.push_back(stringf(" depth => %d\n", size));
+
+ for (int i = 0; i < rd_ports; i++)
+ cell_exprs.push_back(stringf(" reader => r%d\n", i));
+
+ for (int i = 0; i < wr_ports; i++)
+ cell_exprs.push_back(stringf(" writer => w%d\n", i));
+
+ cell_exprs.push_back(stringf(" read-latency => 0\n"));
+ cell_exprs.push_back(stringf(" write-latency => 1\n"));
+ cell_exprs.push_back(stringf(" read-under-write => undefined\n"));
+
+ for (int i = 0; i < rd_ports; i++)
+ {
+ if (rd_clk_enable[i] != State::S0)
+ log_error("Clocked read port %d on memory %s.%s.\n", i, log_id(module), log_id(cell));
+
+ SigSpec data_sig = cell->getPort("\\RD_DATA").extract(i*width, width);
+ string addr_expr = make_expr(cell->getPort("\\RD_ADDR").extract(i*abits, abits));
+
+ cell_exprs.push_back(stringf(" %s.r%d.addr <= %s\n", mem_id.c_str(), i, addr_expr.c_str()));
+ cell_exprs.push_back(stringf(" %s.r%d.en <= UInt<1>(1)\n", mem_id.c_str(), i));
+ cell_exprs.push_back(stringf(" %s.r%d.clk <= asClock(UInt<1>(0))\n", mem_id.c_str(), i));
+
+ register_reverse_wire_map(stringf("%s.r%d.data", mem_id.c_str(), i), data_sig);
+ }
+
+ for (int i = 0; i < wr_ports; i++)
+ {
+ if (wr_clk_enable[i] != State::S1)
+ log_error("Unclocked write port %d on memory %s.%s.\n", i, log_id(module), log_id(cell));
+
+ if (wr_clk_polarity[i] != State::S1)
+ log_error("Negedge write port %d on memory %s.%s.\n", i, log_id(module), log_id(cell));
+
+ string addr_expr = make_expr(cell->getPort("\\WR_ADDR").extract(i*abits, abits));
+ string data_expr = make_expr(cell->getPort("\\WR_DATA").extract(i*width, width));
+ string clk_expr = make_expr(cell->getPort("\\WR_CLK").extract(i));
+
+ SigSpec wen_sig = cell->getPort("\\WR_EN").extract(i*width, width);
+ string wen_expr = make_expr(wen_sig[0]);
+
+ for (int i = 1; i < GetSize(wen_sig); i++)
+ if (wen_sig[0] != wen_sig[i])
+ log_error("Complex write enable on port %d on memory %s.%s.\n", i, log_id(module), log_id(cell));
+
+ cell_exprs.push_back(stringf(" %s.w%d.addr <= %s\n", mem_id.c_str(), i, addr_expr.c_str()));
+ cell_exprs.push_back(stringf(" %s.w%d.data <= %s\n", mem_id.c_str(), i, data_expr.c_str()));
+ cell_exprs.push_back(stringf(" %s.w%d.en <= %s\n", mem_id.c_str(), i, wen_expr.c_str()));
+ cell_exprs.push_back(stringf(" %s.w%d.mask <= UInt<1>(1)\n", mem_id.c_str(), i));
+ cell_exprs.push_back(stringf(" %s.w%d.clk <= asClock(%s)\n", mem_id.c_str(), i, clk_expr.c_str()));
+ }
+
+ continue;
+ }
+
+ if (cell->type.in("$dff"))
+ {
+ bool clkpol = cell->parameters.at("\\CLK_POLARITY").as_bool();
+ if (clkpol == false)
+ log_error("Negative edge clock on FF %s.%s.\n", log_id(module), log_id(cell));
+
+ string q_id = make_id(cell->name);
+ int width = cell->parameters.at("\\WIDTH").as_int();
+ string expr = make_expr(cell->getPort("\\D"));
+ string clk_expr = "asClock(" + make_expr(cell->getPort("\\CLK")) + ")";
+
+ wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s\n", q_id.c_str(), width, clk_expr.c_str()));
+
+ cell_exprs.push_back(stringf(" %s <= %s\n", q_id.c_str(), expr.c_str()));
+ register_reverse_wire_map(q_id, cell->getPort("\\Q"));
+
+ continue;
+ }
+
+ log_error("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell));
+ }
+
+ for (auto conn : module->connections())
+ {
+ string y_id = next_id();
+ int y_width = GetSize(conn.first);
+ string expr = make_expr(conn.second);
+
+ wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width));
+ cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str()));
+ register_reverse_wire_map(y_id, conn.first);
+ }
+
+ for (auto wire : module->wires())
+ {
+ string expr;
+
+ if (wire->port_input)
+ continue;
+
+ int cursor = 0;
+ bool is_valid = false;
+ bool make_unconn_id = false;
+
+ while (cursor < wire->width)
+ {
+ int chunk_width = 1;
+ string new_expr;
+
+ SigBit start_bit(wire, cursor);
+
+ if (reverse_wire_map.count(start_bit))
+ {
+ pair<string, int> start_map = reverse_wire_map.at(start_bit);
+
+ while (cursor+chunk_width < wire->width)
+ {
+ SigBit stop_bit(wire, cursor+chunk_width);
+
+ if (reverse_wire_map.count(stop_bit) == 0)
+ break;
+
+ pair<string, int> stop_map = reverse_wire_map.at(stop_bit);
+ stop_map.second -= chunk_width;
+
+ if (start_map != stop_map)
+ break;
+
+ chunk_width++;
+ }
+
+ new_expr = stringf("bits(%s, %d, %d)", start_map.first.c_str(),
+ start_map.second + chunk_width - 1, start_map.second);
+ is_valid = true;
+ }
+ else
+ {
+ if (unconn_id.empty()) {
+ unconn_id = next_id();
+ make_unconn_id = true;
+ }
+ new_expr = unconn_id;
+ }
+
+ if (expr.empty())
+ expr = new_expr;
+ else
+ expr = "cat(" + new_expr + ", " + expr + ")";
+
+ cursor += chunk_width;
+ }
+
+ if (is_valid) {
+ if (make_unconn_id) {
+ wire_decls.push_back(stringf(" wire %s: UInt<1>\n", unconn_id.c_str()));
+ wire_decls.push_back(stringf(" %s is invalid\n", unconn_id.c_str()));
+ }
+ wire_exprs.push_back(stringf(" %s <= %s\n", make_id(wire->name), expr.c_str()));
+ } else {
+ if (make_unconn_id) {
+ unconn_id.clear();
+ }
+ wire_decls.push_back(stringf(" %s is invalid\n", make_id(wire->name)));
+ }
+ }
+
+ for (auto str : port_decls)
+ f << str;
+
+ f << stringf("\n");
+
+ for (auto str : wire_decls)
+ f << str;
+
+ f << stringf("\n");
+
+ for (auto str : cell_exprs)
+ f << str;
+
+ f << stringf("\n");
+
+ for (auto str : wire_exprs)
+ f << str;
+ }
+};
+
+struct FirrtlBackend : public Backend {
+ FirrtlBackend() : Backend("firrtl", "write design to a FIRRTL file") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" write_firrtl [options] [filename]\n");
+ log("\n");
+ log("Write a FIRRTL netlist of the current design.\n");
+ log("\n");
+ }
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // if (args[argidx] == "-aig") {
+ // aig_mode = true;
+ // continue;
+ // }
+ break;
+ }
+ extra_args(f, filename, args, argidx);
+
+ log_header(design, "Executing FIRRTL backend.\n");
+
+ Module *top = design->top_module();
+
+ if (top == nullptr)
+ log_error("No top module found!\n");
+
+ namecache.clear();
+ autoid_counter = 0;
+
+ for (auto module : design->modules()) {
+ make_id(module->name);
+ for (auto wire : module->wires())
+ if (wire->port_id)
+ make_id(wire->name);
+ }
+
+ *f << stringf("circuit %s:\n", make_id(top->name));
+
+ for (auto module : design->modules())
+ {
+ FirrtlWorker worker(module, *f, design);
+ worker.run();
+ }
+
+ namecache.clear();
+ autoid_counter = 0;
+ }
+} FirrtlBackend;
+
+PRIVATE_NAMESPACE_END
diff --git a/backends/firrtl/test.sh b/backends/firrtl/test.sh
new file mode 100644
index 00000000..fe7e3a32
--- /dev/null
+++ b/backends/firrtl/test.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+set -ex
+
+cd ../../
+make
+cd backends/firrtl
+
+../../yosys -q -p 'prep -nordff; write_firrtl test.fir' $1
+
+firrtl -i test.fir -o test_out.v -ll Info
+
+../../yosys -p "
+ read_verilog $1
+ rename Top gold
+
+ read_verilog test_out.v
+ rename Top gate
+
+ prep
+ memory_map
+ miter -equiv -flatten gold gate miter
+ hierarchy -top miter
+
+ sat -verify -prove trigger 0 -set-init-zero -seq 10 miter
+"
diff --git a/backends/firrtl/test.v b/backends/firrtl/test.v
new file mode 100644
index 00000000..c6d62a84
--- /dev/null
+++ b/backends/firrtl/test.v
@@ -0,0 +1,63 @@
+module test(
+ input clk, wen,
+ input [7:0] uns,
+ input signed [7:0] a, b,
+ input signed [23:0] c,
+ input signed [2:0] sel,
+ output [15:0] s, d, y, z, u, q, p, mul, div, mod, mux, And, Or, Xor, eq, neq, gt, lt, geq, leq, eqx, shr, sshr, shl, sshl, Land, Lor, Lnot, Not, Neg, pos, Andr, Orr, Xorr, Xnorr, Reduce_bool,
+ output [7:0] PMux
+);
+ //initial begin
+ //$display("shr = %b", shr);
+ //end
+ assign s = a+{b[6:2], 2'b1};
+ assign d = a-b;
+ assign y = x;
+ assign z[7:0] = s+d;
+ assign z[15:8] = s-d;
+ assign p = a & b | x;
+ assign mul = a * b;
+ assign div = a / b;
+ assign mod = a % b;
+ assign mux = x[0] ? a : b;
+ assign And = a & b;
+ assign Or = a | b;
+ assign Xor = a ^ b;
+ assign Not = ~a;
+ assign Neg = -a;
+ assign eq = a == b;
+ assign neq = a != b;
+ assign gt = a > b;
+ assign lt = a < b;
+ assign geq = a >= b;
+ assign leq = a <= b;
+ assign eqx = a === b;
+ assign shr = a >> b; //0111111111000000
+ assign sshr = a >>> b;
+ assign shl = a << b;
+ assign sshl = a <<< b;
+ assign Land = a && b;
+ assign Lor = a || b;
+ assign Lnot = !a;
+ assign pos = $signed(uns);
+ assign Andr = &a;
+ assign Orr = |a;
+ assign Xorr = ^a;
+ assign Xnorr = ~^a;
+ always @*
+ if(!a) begin
+ Reduce_bool = a;
+ end else begin
+ Reduce_bool = b;
+ end
+ //always @(sel or c or a)
+ // begin
+ // case (sel)
+ // 3'b000: PMux = a;
+ // 3'b001: PMux = c[7:0];
+ // 3'b010: PMux = c[15:8];
+ // 3'b100: PMux = c[23:16];
+ // endcase
+ // end
+
+endmodule
diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc
index 16d1a97f..4c58ea08 100644
--- a/backends/ilang/ilang_backend.cc
+++ b/backends/ilang/ilang_backend.cc
@@ -219,7 +219,7 @@ void ILANG_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT
{
f << stringf("%s" "sync ", indent.c_str());
switch (sy->type) {
- if (0) case RTLIL::ST0: f << stringf("low ");
+ case RTLIL::ST0: f << stringf("low ");
if (0) case RTLIL::ST1: f << stringf("high ");
if (0) case RTLIL::STp: f << stringf("posedge ");
if (0) case RTLIL::STn: f << stringf("negedge ");
@@ -382,7 +382,7 @@ PRIVATE_NAMESPACE_BEGIN
struct IlangBackend : public Backend {
IlangBackend() : Backend("ilang", "write design to ilang file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -395,7 +395,7 @@ struct IlangBackend : public Backend {
log(" only write selected parts of the design.\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool selected = false;
@@ -422,7 +422,7 @@ struct IlangBackend : public Backend {
struct DumpPass : public Pass {
DumpPass() : Pass("dump", "print parts of the design in ilang format") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -445,7 +445,7 @@ struct DumpPass : public Pass {
log(" like -outfile but append instead of overwrite\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string filename;
bool flag_m = false, flag_n = false, append = false;
diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc
index 34cb52fb..2eb08dbe 100644
--- a/backends/intersynth/intersynth.cc
+++ b/backends/intersynth/intersynth.cc
@@ -46,7 +46,7 @@ static std::string netname(std::set<std::string> &conntypes_code, std::set<std::
struct IntersynthBackend : public Backend {
IntersynthBackend() : Backend("intersynth", "write design to InterSynth netlist file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -71,7 +71,7 @@ struct IntersynthBackend : public Backend {
log("http://www.clifford.at/intersynth/\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing INTERSYNTH backend.\n");
log_push();
diff --git a/backends/json/json.cc b/backends/json/json.cc
index 4baffa33..f5c68798 100644
--- a/backends/json/json.cc
+++ b/backends/json/json.cc
@@ -93,8 +93,10 @@ struct JsonWriter
f << get_string(param.second.decode_string());
else if (GetSize(param.second.bits) > 32)
f << get_string(param.second.as_string());
- else
+ else if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0)
f << stringf("%d", param.second.as_int());
+ else
+ f << stringf("%u", param.second.as_int());
first = false;
}
}
@@ -201,6 +203,8 @@ struct JsonWriter
void write_design(Design *design_)
{
design = design_;
+ design->sort();
+
f << stringf("{\n");
f << stringf(" \"creator\": %s,\n", get_string(yosys_version_str).c_str());
f << stringf(" \"modules\": {\n");
@@ -248,7 +252,7 @@ struct JsonWriter
struct JsonBackend : public Backend {
JsonBackend() : Backend("json", "write design to a JSON file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -333,6 +337,10 @@ struct JsonBackend : public Backend {
log("connected to a constant driver are denoted as string \"0\" or \"1\" instead of\n");
log("a number.\n");
log("\n");
+ log("Numeric parameter and attribute values up to 32 bits are written as decimal\n");
+ log("values. Numbers larger than that are written as string holding the binary\n");
+ log("representation of the value.\n");
+ log("\n");
log("For example the following Verilog code:\n");
log("\n");
log(" module test(input x, y);\n");
@@ -452,7 +460,7 @@ struct JsonBackend : public Backend {
log("format. A program processing this format must ignore all unknown fields.\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
bool aig_mode = false;
@@ -476,7 +484,7 @@ struct JsonBackend : public Backend {
struct JsonPass : public Pass {
JsonPass() : Pass("json", "write design in JSON format") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -493,7 +501,7 @@ struct JsonPass : public Pass {
log("See 'help write_json' for a description of the JSON format used.\n");
log("\n");
}
- virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string filename;
bool aig_mode = false;
diff --git a/backends/protobuf/.gitignore b/backends/protobuf/.gitignore
new file mode 100644
index 00000000..849b38d4
--- /dev/null
+++ b/backends/protobuf/.gitignore
@@ -0,0 +1,2 @@
+yosys.pb.cc
+yosys.pb.h
diff --git a/backends/protobuf/Makefile.inc b/backends/protobuf/Makefile.inc
new file mode 100644
index 00000000..834cad42
--- /dev/null
+++ b/backends/protobuf/Makefile.inc
@@ -0,0 +1,8 @@
+ifeq ($(ENABLE_PROTOBUF),1)
+
+backends/protobuf/yosys.pb.cc backends/protobuf/yosys.pb.h: misc/yosys.proto
+ $(Q) cd misc && protoc --cpp_out "../backends/protobuf" yosys.proto
+
+OBJS += backends/protobuf/protobuf.o backends/protobuf/yosys.pb.o
+
+endif
diff --git a/backends/protobuf/protobuf.cc b/backends/protobuf/protobuf.cc
new file mode 100644
index 00000000..f56147ce
--- /dev/null
+++ b/backends/protobuf/protobuf.cc
@@ -0,0 +1,370 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <google/protobuf/text_format.h>
+
+#include "kernel/rtlil.h"
+#include "kernel/register.h"
+#include "kernel/sigtools.h"
+#include "kernel/celltypes.h"
+#include "kernel/cellaigs.h"
+#include "kernel/log.h"
+#include "yosys.pb.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct ProtobufDesignSerializer
+{
+ bool aig_mode_;
+ bool use_selection_;
+ yosys::pb::Design *pb_;
+
+ Design *design_;
+ Module *module_;
+
+ SigMap sigmap_;
+ int sigidcounter_;
+ dict<SigBit, uint64_t> sigids_;
+ pool<Aig> aig_models_;
+
+
+ ProtobufDesignSerializer(bool use_selection, bool aig_mode) :
+ aig_mode_(aig_mode), use_selection_(use_selection) { }
+
+ string get_name(IdString name)
+ {
+ return RTLIL::unescape_id(name);
+ }
+
+
+ void serialize_parameters(google::protobuf::Map<std::string, yosys::pb::Parameter> *out,
+ const dict<IdString, Const> &parameters)
+ {
+ for (auto &param : parameters) {
+ std::string key = get_name(param.first);
+
+
+ yosys::pb::Parameter pb_param;
+
+ if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) {
+ pb_param.set_str(param.second.decode_string());
+ } else if (GetSize(param.second.bits) > 64) {
+ pb_param.set_str(param.second.as_string());
+ } else {
+ pb_param.set_int_(param.second.as_int());
+ }
+
+ (*out)[key] = pb_param;
+ }
+ }
+
+ void get_bits(yosys::pb::BitVector *out, SigSpec sig)
+ {
+ for (auto bit : sigmap_(sig)) {
+ auto sig = out->add_signal();
+
+ // Constant driver.
+ if (bit.wire == nullptr) {
+ if (bit == State::S0) sig->set_constant(sig->CONSTANT_DRIVER_LOW);
+ else if (bit == State::S1) sig->set_constant(sig->CONSTANT_DRIVER_HIGH);
+ else if (bit == State::Sz) sig->set_constant(sig->CONSTANT_DRIVER_Z);
+ else sig->set_constant(sig->CONSTANT_DRIVER_X);
+ continue;
+ }
+
+ // Signal - give it a unique identifier.
+ if (sigids_.count(bit) == 0) {
+ sigids_[bit] = sigidcounter_++;
+ }
+ sig->set_id(sigids_[bit]);
+ }
+ }
+
+ void serialize_module(yosys::pb::Module* out, Module *module)
+ {
+ module_ = module;
+ log_assert(module_->design == design_);
+ sigmap_.set(module_);
+ sigids_.clear();
+ sigidcounter_ = 0;
+
+ serialize_parameters(out->mutable_attribute(), module_->attributes);
+
+ for (auto n : module_->ports) {
+ Wire *w = module->wire(n);
+ if (use_selection_ && !module_->selected(w))
+ continue;
+
+ yosys::pb::Module::Port pb_port;
+ pb_port.set_direction(w->port_input ? w->port_output ?
+ yosys::pb::DIRECTION_INOUT : yosys::pb::DIRECTION_INPUT : yosys::pb::DIRECTION_OUTPUT);
+ get_bits(pb_port.mutable_bits(), w);
+ (*out->mutable_port())[get_name(n)] = pb_port;
+ }
+
+ for (auto c : module_->cells()) {
+ if (use_selection_ && !module_->selected(c))
+ continue;
+
+ yosys::pb::Module::Cell pb_cell;
+ pb_cell.set_hide_name(c->name[0] == '$');
+ pb_cell.set_type(get_name(c->type));
+
+ if (aig_mode_) {
+ Aig aig(c);
+ if (aig.name.empty())
+ continue;
+ pb_cell.set_model(aig.name);
+ aig_models_.insert(aig);
+ }
+ serialize_parameters(pb_cell.mutable_parameter(), c->parameters);
+ serialize_parameters(pb_cell.mutable_attribute(), c->attributes);
+
+ if (c->known()) {
+ for (auto &conn : c->connections()) {
+ yosys::pb::Direction direction = yosys::pb::DIRECTION_OUTPUT;
+ if (c->input(conn.first))
+ direction = c->output(conn.first) ? yosys::pb::DIRECTION_INOUT : yosys::pb::DIRECTION_INPUT;
+ (*pb_cell.mutable_port_direction())[get_name(conn.first)] = direction;
+ }
+ }
+ for (auto &conn : c->connections()) {
+ yosys::pb::BitVector vec;
+ get_bits(&vec, conn.second);
+ (*pb_cell.mutable_connection())[get_name(conn.first)] = vec;
+ }
+
+ (*out->mutable_cell())[get_name(c->name)] = pb_cell;
+ }
+
+ for (auto w : module_->wires()) {
+ if (use_selection_ && !module_->selected(w))
+ continue;
+
+ auto netname = out->add_netname();
+ netname->set_hide_name(w->name[0] == '$');
+ get_bits(netname->mutable_bits(), w);
+ serialize_parameters(netname->mutable_attributes(), w->attributes);
+ }
+ }
+
+
+ void serialize_models(google::protobuf::Map<string, yosys::pb::Model> *models)
+ {
+ for (auto &aig : aig_models_) {
+ yosys::pb::Model pb_model;
+ for (auto &node : aig.nodes) {
+ auto pb_node = pb_model.add_node();
+ if (node.portbit >= 0) {
+ if (node.inverter) {
+ pb_node->set_type(pb_node->TYPE_NPORT);
+ } else {
+ pb_node->set_type(pb_node->TYPE_PORT);
+ }
+ auto port = pb_node->mutable_port();
+ port->set_portname(log_id(node.portname));
+ port->set_bitindex(node.portbit);
+ } else if (node.left_parent < 0 && node.right_parent < 0) {
+ if (node.inverter) {
+ pb_node->set_type(pb_node->TYPE_TRUE);
+ } else {
+ pb_node->set_type(pb_node->TYPE_FALSE);
+ }
+ } else {
+ if (node.inverter) {
+ pb_node->set_type(pb_node->TYPE_NAND);
+ } else {
+ pb_node->set_type(pb_node->TYPE_AND);
+ }
+ auto gate = pb_node->mutable_gate();
+ gate->set_left(node.left_parent);
+ gate->set_right(node.right_parent);
+ }
+ for (auto &op : node.outports) {
+ auto pb_op = pb_node->add_out_port();
+ pb_op->set_name(log_id(op.first));
+ pb_op->set_bit_index(op.second);
+ }
+ }
+ (*models)[aig.name] = pb_model;
+ }
+ }
+
+ void serialize_design(yosys::pb::Design *pb, Design *design)
+ {
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+ pb_ = pb;
+ pb_->Clear();
+ pb_->set_creator(yosys_version_str);
+
+ design_ = design;
+ design_->sort();
+
+ auto modules = use_selection_ ? design_->selected_modules() : design_->modules();
+ for (auto mod : modules) {
+ yosys::pb::Module pb_mod;
+ serialize_module(&pb_mod, mod);
+ (*pb->mutable_modules())[mod->name.str()] = pb_mod;
+ }
+
+ serialize_models(pb_->mutable_models());
+ }
+};
+
+struct ProtobufBackend : public Backend {
+ ProtobufBackend(): Backend("protobuf", "write design to a Protocol Buffer file") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" write_protobuf [options] [filename]\n");
+ log("\n");
+ log("Write a JSON netlist of the current design.\n");
+ log("\n");
+ log(" -aig\n");
+ log(" include AIG models for the different gate types\n");
+ log("\n");
+ log(" -text\n");
+ log(" output protobuf in Text/ASCII representation\n");
+ log("\n");
+ log("The schema of the output Protocol Buffer is defined in misc/yosys.pb in the\n");
+ log("Yosys source code distribution.\n");
+ log("\n");
+ }
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ bool aig_mode = false;
+ bool text_mode = false;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-aig") {
+ aig_mode = true;
+ continue;
+ }
+ if (args[argidx] == "-text") {
+ text_mode = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(f, filename, args, argidx);
+
+ log_header(design, "Executing Protobuf backend.\n");
+
+ yosys::pb::Design pb;
+ ProtobufDesignSerializer serializer(false, aig_mode);
+ serializer.serialize_design(&pb, design);
+
+ if (text_mode) {
+ string out;
+ google::protobuf::TextFormat::PrintToString(pb, &out);
+ *f << out;
+ } else {
+ pb.SerializeToOstream(f);
+ }
+ }
+} ProtobufBackend;
+
+struct ProtobufPass : public Pass {
+ ProtobufPass() : Pass("protobuf", "write design in Protobuf format") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" protobuf [options] [selection]\n");
+ log("\n");
+ log("Write a JSON netlist of all selected objects.\n");
+ log("\n");
+ log(" -o <filename>\n");
+ log(" write to the specified file.\n");
+ log("\n");
+ log(" -aig\n");
+ log(" include AIG models for the different gate types\n");
+ log("\n");
+ log(" -text\n");
+ log(" output protobuf in Text/ASCII representation\n");
+ log("\n");
+ log("The schema of the output Protocol Buffer is defined in misc/yosys.pb in the\n");
+ log("Yosys source code distribution.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ std::string filename;
+ bool aig_mode = false;
+ bool text_mode = false;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-o" && argidx+1 < args.size()) {
+ filename = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-aig") {
+ aig_mode = true;
+ continue;
+ }
+ if (args[argidx] == "-text") {
+ text_mode = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ std::ostream *f;
+ std::stringstream buf;
+
+ if (!filename.empty()) {
+ std::ofstream *ff = new std::ofstream;
+ ff->open(filename.c_str(), std::ofstream::trunc);
+ if (ff->fail()) {
+ delete ff;
+ log_error("Can't open file `%s' for writing: %s\n", filename.c_str(), strerror(errno));
+ }
+ f = ff;
+ } else {
+ f = &buf;
+ }
+
+ yosys::pb::Design pb;
+ ProtobufDesignSerializer serializer(true, aig_mode);
+ serializer.serialize_design(&pb, design);
+
+ if (text_mode) {
+ string out;
+ google::protobuf::TextFormat::PrintToString(pb, &out);
+ *f << out;
+ } else {
+ pb.SerializeToOstream(f);
+ }
+
+ if (!filename.empty()) {
+ delete f;
+ } else {
+ log("%s", buf.str().c_str());
+ }
+ }
+} ProtobufPass;
+
+PRIVATE_NAMESPACE_END;
diff --git a/backends/simplec/.gitignore b/backends/simplec/.gitignore
new file mode 100644
index 00000000..f0879616
--- /dev/null
+++ b/backends/simplec/.gitignore
@@ -0,0 +1,2 @@
+test00_tb
+test00_uut.c
diff --git a/backends/simplec/Makefile.inc b/backends/simplec/Makefile.inc
new file mode 100644
index 00000000..fee1376c
--- /dev/null
+++ b/backends/simplec/Makefile.inc
@@ -0,0 +1,3 @@
+
+OBJS += backends/simplec/simplec.o
+
diff --git a/backends/simplec/simplec.cc b/backends/simplec/simplec.cc
new file mode 100644
index 00000000..349bc5a6
--- /dev/null
+++ b/backends/simplec/simplec.cc
@@ -0,0 +1,810 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+#include "kernel/utils.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct HierDirtyFlags;
+
+static pool<string> reserved_cids;
+static dict<IdString, string> id2cid;
+
+static string cid(IdString id)
+{
+ if (id2cid.count(id) == 0)
+ {
+ string s = id.str();
+ if (GetSize(s) < 2) log_abort();
+
+ if (s[0] == '\\')
+ s = s.substr(1);
+
+ if ('0' <= s[0] && s[0] <= '9') {
+ s = "_" + s;
+ }
+
+ for (int i = 0; i < GetSize(s); i++) {
+ if ('0' <= s[i] && s[i] <= '9') continue;
+ if ('A' <= s[i] && s[i] <= 'Z') continue;
+ if ('a' <= s[i] && s[i] <= 'z') continue;
+ s[i] = '_';
+ }
+
+ while (reserved_cids.count(s))
+ s += "_";
+
+ reserved_cids.insert(s);
+ id2cid[id] = s;
+ }
+
+ return id2cid.at(id);
+}
+
+struct HierDirtyFlags
+{
+ int dirty;
+ Module *module;
+ IdString hiername;
+ HierDirtyFlags *parent;
+ pool<SigBit> dirty_bits;
+ pool<Cell*> dirty_cells;
+ pool<SigBit> sticky_dirty_bits;
+ dict<IdString, HierDirtyFlags*> children;
+ string prefix, log_prefix;
+
+ HierDirtyFlags(Module *module, IdString hiername, HierDirtyFlags *parent, const string &prefix, const string &log_prefix) :
+ dirty(0), module(module), hiername(hiername), parent(parent), prefix(prefix), log_prefix(log_prefix)
+ {
+ for (Cell *cell : module->cells()) {
+ Module *mod = module->design->module(cell->type);
+ if (mod) children[cell->name] = new HierDirtyFlags(mod, cell->name, this,
+ prefix + cid(cell->name) + ".", log_prefix + "." + prefix + log_id(cell->name));
+ }
+ }
+
+ ~HierDirtyFlags()
+ {
+ for (auto &child : children)
+ delete child.second;
+ }
+
+ void set_dirty(SigBit bit)
+ {
+ if (dirty_bits.count(bit))
+ return;
+
+ dirty_bits.insert(bit);
+ sticky_dirty_bits.insert(bit);
+
+ HierDirtyFlags *p = this;
+ while (p != nullptr) {
+ p->dirty++;
+ p = p->parent;
+ }
+ }
+
+ void unset_dirty(SigBit bit)
+ {
+ if (dirty_bits.count(bit) == 0)
+ return;
+
+ dirty_bits.erase(bit);
+
+ HierDirtyFlags *p = this;
+ while (p != nullptr) {
+ p->dirty--;
+ log_assert(p->dirty >= 0);
+ p = p->parent;
+ }
+ }
+
+ void set_dirty(Cell *cell)
+ {
+ if (dirty_cells.count(cell))
+ return;
+
+ dirty_cells.insert(cell);
+
+ HierDirtyFlags *p = this;
+ while (p != nullptr) {
+ p->dirty++;
+ p = p->parent;
+ }
+ }
+
+ void unset_dirty(Cell *cell)
+ {
+ if (dirty_cells.count(cell) == 0)
+ return;
+
+ dirty_cells.erase(cell);
+
+ HierDirtyFlags *p = this;
+ while (p != nullptr) {
+ p->dirty--;
+ log_assert(p->dirty >= 0);
+ p = p->parent;
+ }
+ }
+};
+
+struct SimplecWorker
+{
+ bool verbose = false;
+ int max_uintsize = 32;
+
+ Design *design;
+ dict<Module*, SigMap> sigmaps;
+
+ vector<string> signal_declarations;
+ pool<int> generated_sigtypes;
+
+ vector<string> util_declarations;
+ pool<string> generated_utils;
+
+ vector<string> struct_declarations;
+ pool<IdString> generated_structs;
+
+ vector<string> funct_declarations;
+
+ dict<Module*, dict<SigBit, pool<tuple<Cell*, IdString, int>>>> bit2cell;
+ dict<Module*, dict<SigBit, pool<SigBit>>> bit2output;
+ dict<Module*, pool<SigBit>> driven_bits;
+
+ dict<Cell*, int> topoidx;
+
+ pool<string> activated_cells;
+ pool<string> reactivated_cells;
+
+ SimplecWorker(Design *design) : design(design)
+ {
+ }
+
+ string sigtype(int n)
+ {
+ string struct_name = stringf("signal%d_t", n);
+
+ if (generated_sigtypes.count(n) == 0)
+ {
+ signal_declarations.push_back("");
+ signal_declarations.push_back(stringf("#ifndef YOSYS_SIMPLEC_SIGNAL%d_T", n));
+ signal_declarations.push_back(stringf("#define YOSYS_SIMPLEC_SIGNAL%d_T", n));
+ signal_declarations.push_back(stringf("typedef struct {"));
+
+ for (int k = 8; k <= max_uintsize; k = 2*k)
+ if (n <= k && k <= max_uintsize) {
+ signal_declarations.push_back(stringf(" uint%d_t value_%d_0 : %d;", k, n-1, n));
+ goto end_struct;
+ }
+
+ for (int k = 0; k < n; k += max_uintsize) {
+ int bits = std::min(max_uintsize, n-k);
+ signal_declarations.push_back(stringf(" uint%d_t value_%d_%d : %d;", max_uintsize, k+bits-1, k, bits));
+ }
+
+ end_struct:
+ signal_declarations.push_back(stringf("} signal%d_t;", n));
+ signal_declarations.push_back(stringf("#endif"));
+ generated_sigtypes.insert(n);
+ }
+
+ return struct_name;
+ }
+
+ void util_ifdef_guard(string s)
+ {
+ for (int i = 0; i < GetSize(s); i++)
+ if ('a' <= s[i] && s[i] <= 'z')
+ s[i] -= 'a' - 'A';
+
+ util_declarations.push_back("");
+ util_declarations.push_back(stringf("#ifndef %s", s.c_str()));
+ util_declarations.push_back(stringf("#define %s", s.c_str()));
+ }
+
+ string util_get_bit(const string &signame, int n, int idx)
+ {
+ if (n == 1 && idx == 0)
+ return signame + ".value_0_0";
+
+ string util_name = stringf("yosys_simplec_get_bit_%d_of_%d", idx, n);
+
+ if (generated_utils.count(util_name) == 0)
+ {
+ util_ifdef_guard(util_name);
+ util_declarations.push_back(stringf("static inline bool %s(const %s *sig)", util_name.c_str(), sigtype(n).c_str()));
+ util_declarations.push_back(stringf("{"));
+
+ int word_idx = idx / max_uintsize, word_offset = idx % max_uintsize;
+ string value_name = stringf("value_%d_%d", std::min(n-1, (word_idx+1)*max_uintsize-1), word_idx*max_uintsize);
+
+ util_declarations.push_back(stringf(" return (sig->%s >> %d) & 1;", value_name.c_str(), word_offset));
+
+ util_declarations.push_back(stringf("}"));
+ util_declarations.push_back(stringf("#endif"));
+ generated_utils.insert(util_name);
+ }
+
+ return stringf("%s(&%s)", util_name.c_str(), signame.c_str());
+ }
+
+ string util_set_bit(const string &signame, int n, int idx, const string &expr)
+ {
+ if (n == 1 && idx == 0)
+ return stringf(" %s.value_0_0 = %s;", signame.c_str(), expr.c_str());
+
+ string util_name = stringf("yosys_simplec_set_bit_%d_of_%d", idx, n);
+
+ if (generated_utils.count(util_name) == 0)
+ {
+ util_ifdef_guard(util_name);
+ util_declarations.push_back(stringf("static inline void %s(%s *sig, bool value)", util_name.c_str(), sigtype(n).c_str()));
+ util_declarations.push_back(stringf("{"));
+
+ int word_idx = idx / max_uintsize, word_offset = idx % max_uintsize;
+ string value_name = stringf("value_%d_%d", std::min(n-1, (word_idx+1)*max_uintsize-1), word_idx*max_uintsize);
+
+ #if 0
+ util_declarations.push_back(stringf(" if (value)"));
+ util_declarations.push_back(stringf(" sig->%s |= 1UL << %d;", value_name.c_str(), word_offset));
+ util_declarations.push_back(stringf(" else"));
+ util_declarations.push_back(stringf(" sig->%s &= ~(1UL << %d);", value_name.c_str(), word_offset));
+ #else
+ util_declarations.push_back(stringf(" sig->%s = (sig->%s & ~((uint%d_t)1 << %d)) | ((uint%d_t)value << %d);",
+ value_name.c_str(), value_name.c_str(), max_uintsize, word_offset, max_uintsize, word_offset));
+ #endif
+
+ util_declarations.push_back(stringf("}"));
+ util_declarations.push_back(stringf("#endif"));
+ generated_utils.insert(util_name);
+ }
+
+ return stringf(" %s(&%s, %s);", util_name.c_str(), signame.c_str(), expr.c_str());
+ }
+
+ void create_module_struct(Module *mod)
+ {
+ if (generated_structs.count(mod->name))
+ return;
+
+ generated_structs.insert(mod->name);
+ sigmaps[mod].set(mod);
+
+ for (Wire *w : mod->wires())
+ {
+ if (w->port_output)
+ for (auto bit : SigSpec(w))
+ bit2output[mod][sigmaps.at(mod)(bit)].insert(bit);
+ }
+
+ for (Cell *c : mod->cells())
+ {
+ for (auto &conn : c->connections())
+ {
+ if (!c->input(conn.first)) {
+ for (auto bit : sigmaps.at(mod)(conn.second))
+ driven_bits[mod].insert(bit);
+ continue;
+ }
+
+ int idx = 0;
+ for (auto bit : sigmaps.at(mod)(conn.second))
+ bit2cell[mod][bit].insert(tuple<Cell*, IdString, int>(c, conn.first, idx++));
+ }
+
+ if (design->module(c->type))
+ create_module_struct(design->module(c->type));
+ }
+
+ TopoSort<IdString> topo;
+
+ for (Cell *c : mod->cells())
+ {
+ topo.node(c->name);
+
+ for (auto &conn : c->connections())
+ {
+ if (!c->input(conn.first))
+ continue;
+
+ for (auto bit : sigmaps.at(mod)(conn.second))
+ for (auto &it : bit2cell[mod][bit])
+ topo.edge(c->name, std::get<0>(it)->name);
+ }
+ }
+
+ topo.analyze_loops = false;
+ topo.sort();
+
+ for (int i = 0; i < GetSize(topo.sorted); i++)
+ topoidx[mod->cell(topo.sorted[i])] = i;
+
+ string ifdef_name = stringf("yosys_simplec_%s_state_t", cid(mod->name).c_str());
+
+ for (int i = 0; i < GetSize(ifdef_name); i++)
+ if ('a' <= ifdef_name[i] && ifdef_name[i] <= 'z')
+ ifdef_name[i] -= 'a' - 'A';
+
+ struct_declarations.push_back("");
+ struct_declarations.push_back(stringf("#ifndef %s", ifdef_name.c_str()));
+ struct_declarations.push_back(stringf("#define %s", ifdef_name.c_str()));
+ struct_declarations.push_back(stringf("struct %s_state_t", cid(mod->name).c_str()));
+ struct_declarations.push_back("{");
+
+ struct_declarations.push_back(" // Input Ports");
+ for (Wire *w : mod->wires())
+ if (w->port_input)
+ struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w)));
+
+ struct_declarations.push_back("");
+ struct_declarations.push_back(" // Output Ports");
+ for (Wire *w : mod->wires())
+ if (!w->port_input && w->port_output)
+ struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w)));
+
+ struct_declarations.push_back("");
+ struct_declarations.push_back(" // Internal Wires");
+ for (Wire *w : mod->wires())
+ if (!w->port_input && !w->port_output)
+ struct_declarations.push_back(stringf(" %s %s; // %s", sigtype(w->width).c_str(), cid(w->name).c_str(), log_id(w)));
+
+ for (Cell *c : mod->cells())
+ if (design->module(c->type))
+ struct_declarations.push_back(stringf(" struct %s_state_t %s; // %s", cid(c->type).c_str(), cid(c->name).c_str(), log_id(c)));
+
+ struct_declarations.push_back(stringf("};"));
+ struct_declarations.push_back("#endif");
+ }
+
+ void eval_cell(HierDirtyFlags *work, Cell *cell)
+ {
+ if (cell->type.in("$_BUF_", "$_NOT_"))
+ {
+ SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
+ SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
+
+ string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
+ string expr;
+
+ if (cell->type == "$_BUF_") expr = a_expr;
+ if (cell->type == "$_NOT_") expr = "!" + a_expr;
+
+ log_assert(y.wire);
+ funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
+ stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
+
+ work->set_dirty(y);
+ return;
+ }
+
+ if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_"))
+ {
+ SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
+ SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
+ SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
+
+ string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
+ string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
+ string expr;
+
+ if (cell->type == "$_AND_") expr = stringf("%s & %s", a_expr.c_str(), b_expr.c_str());
+ if (cell->type == "$_NAND_") expr = stringf("!(%s & %s)", a_expr.c_str(), b_expr.c_str());
+ if (cell->type == "$_OR_") expr = stringf("%s | %s", a_expr.c_str(), b_expr.c_str());
+ if (cell->type == "$_NOR_") expr = stringf("!(%s | %s)", a_expr.c_str(), b_expr.c_str());
+ if (cell->type == "$_XOR_") expr = stringf("%s ^ %s", a_expr.c_str(), b_expr.c_str());
+ if (cell->type == "$_XNOR_") expr = stringf("!(%s ^ %s)", a_expr.c_str(), b_expr.c_str());
+ if (cell->type == "$_ANDNOT_") expr = stringf("%s & (!%s)", a_expr.c_str(), b_expr.c_str());
+ if (cell->type == "$_ORNOT_") expr = stringf("%s | (!%s)", a_expr.c_str(), b_expr.c_str());
+
+ log_assert(y.wire);
+ funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
+ stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
+
+ work->set_dirty(y);
+ return;
+ }
+
+ if (cell->type.in("$_AOI3_", "$_OAI3_"))
+ {
+ SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
+ SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
+ SigBit c = sigmaps.at(work->module)(cell->getPort("\\C"));
+ SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
+
+ string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
+ string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
+ string c_expr = c.wire ? util_get_bit(work->prefix + cid(c.wire->name), c.wire->width, c.offset) : c.data ? "1" : "0";
+ string expr;
+
+ if (cell->type == "$_AOI3_") expr = stringf("!((%s & %s) | %s)", a_expr.c_str(), b_expr.c_str(), c_expr.c_str());
+ if (cell->type == "$_OAI3_") expr = stringf("!((%s | %s) & %s)", a_expr.c_str(), b_expr.c_str(), c_expr.c_str());
+
+ log_assert(y.wire);
+ funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
+ stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
+
+ work->set_dirty(y);
+ return;
+ }
+
+ if (cell->type.in("$_AOI4_", "$_OAI4_"))
+ {
+ SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
+ SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
+ SigBit c = sigmaps.at(work->module)(cell->getPort("\\C"));
+ SigBit d = sigmaps.at(work->module)(cell->getPort("\\D"));
+ SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
+
+ string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
+ string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
+ string c_expr = c.wire ? util_get_bit(work->prefix + cid(c.wire->name), c.wire->width, c.offset) : c.data ? "1" : "0";
+ string d_expr = d.wire ? util_get_bit(work->prefix + cid(d.wire->name), d.wire->width, d.offset) : d.data ? "1" : "0";
+ string expr;
+
+ if (cell->type == "$_AOI4_") expr = stringf("!((%s & %s) | (%s & %s))", a_expr.c_str(), b_expr.c_str(), c_expr.c_str(), d_expr.c_str());
+ if (cell->type == "$_OAI4_") expr = stringf("!((%s | %s) & (%s | %s))", a_expr.c_str(), b_expr.c_str(), c_expr.c_str(), d_expr.c_str());
+
+ log_assert(y.wire);
+ funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
+ stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
+
+ work->set_dirty(y);
+ return;
+ }
+
+ if (cell->type == "$_MUX_")
+ {
+ SigBit a = sigmaps.at(work->module)(cell->getPort("\\A"));
+ SigBit b = sigmaps.at(work->module)(cell->getPort("\\B"));
+ SigBit s = sigmaps.at(work->module)(cell->getPort("\\S"));
+ SigBit y = sigmaps.at(work->module)(cell->getPort("\\Y"));
+
+ string a_expr = a.wire ? util_get_bit(work->prefix + cid(a.wire->name), a.wire->width, a.offset) : a.data ? "1" : "0";
+ string b_expr = b.wire ? util_get_bit(work->prefix + cid(b.wire->name), b.wire->width, b.offset) : b.data ? "1" : "0";
+ string s_expr = s.wire ? util_get_bit(work->prefix + cid(s.wire->name), s.wire->width, s.offset) : s.data ? "1" : "0";
+
+ // casts to bool are a workaround for CBMC bug (https://github.com/diffblue/cbmc/issues/933)
+ string expr = stringf("%s ? (bool)%s : (bool)%s", s_expr.c_str(), b_expr.c_str(), a_expr.c_str());
+
+ log_assert(y.wire);
+ funct_declarations.push_back(util_set_bit(work->prefix + cid(y.wire->name), y.wire->width, y.offset, expr) +
+ stringf(" // %s (%s)", log_id(cell), log_id(cell->type)));
+
+ work->set_dirty(y);
+ return;
+ }
+
+ log_error("No C model for %s available at the moment (FIXME).\n", log_id(cell->type));
+ }
+
+ void eval_dirty(HierDirtyFlags *work)
+ {
+ while (work->dirty)
+ {
+ if (verbose && (!work->dirty_bits.empty() || !work->dirty_cells.empty()))
+ log(" In %s:\n", work->log_prefix.c_str());
+
+ while (!work->dirty_bits.empty() || !work->dirty_cells.empty())
+ {
+ if (!work->dirty_bits.empty())
+ {
+ SigSpec dirtysig(work->dirty_bits);
+ dirtysig.sort_and_unify();
+
+ for (SigChunk chunk : dirtysig.chunks()) {
+ if (chunk.wire == nullptr)
+ continue;
+ if (verbose)
+ log(" Propagating %s.%s[%d:%d].\n", work->log_prefix.c_str(), log_id(chunk.wire), chunk.offset+chunk.width-1, chunk.offset);
+ funct_declarations.push_back(stringf(" // Updated signal in %s: %s", work->log_prefix.c_str(), log_signal(chunk)));
+ }
+
+ for (SigBit bit : dirtysig)
+ {
+ if (bit2output[work->module].count(bit) && work->parent)
+ for (auto outbit : bit2output[work->module][bit])
+ {
+ Module *parent_mod = work->parent->module;
+ Cell *parent_cell = parent_mod->cell(work->hiername);
+
+ IdString port_name = outbit.wire->name;
+ int port_offset = outbit.offset;
+ SigBit parent_bit = sigmaps.at(parent_mod)(parent_cell->getPort(port_name)[port_offset]);
+
+ log_assert(bit.wire && parent_bit.wire);
+ funct_declarations.push_back(util_set_bit(work->parent->prefix + cid(parent_bit.wire->name), parent_bit.wire->width, parent_bit.offset,
+ util_get_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset)));
+ work->parent->set_dirty(parent_bit);
+
+ if (verbose)
+ log(" Propagating %s.%s[%d] -> %s.%s[%d].\n", work->log_prefix.c_str(), log_id(bit.wire), bit.offset,
+ work->parent->log_prefix.c_str(), log_id(parent_bit.wire), parent_bit.offset);
+ }
+
+ for (auto &port : bit2cell[work->module][bit])
+ {
+ if (work->children.count(std::get<0>(port)->name))
+ {
+ HierDirtyFlags *child = work->children.at(std::get<0>(port)->name);
+ SigBit child_bit = sigmaps.at(child->module)(SigBit(child->module->wire(std::get<1>(port)), std::get<2>(port)));
+ log_assert(bit.wire && child_bit.wire);
+
+ funct_declarations.push_back(util_set_bit(work->prefix + cid(child->hiername) + "." + cid(child_bit.wire->name),
+ child_bit.wire->width, child_bit.offset, util_get_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset)));
+ child->set_dirty(child_bit);
+
+ if (verbose)
+ log(" Propagating %s.%s[%d] -> %s.%s.%s[%d].\n", work->log_prefix.c_str(), log_id(bit.wire), bit.offset,
+ work->log_prefix.c_str(), log_id(std::get<0>(port)), log_id(child_bit.wire), child_bit.offset);
+ } else {
+ if (verbose)
+ log(" Marking cell %s.%s (via %s.%s[%d]).\n", work->log_prefix.c_str(), log_id(std::get<0>(port)),
+ work->log_prefix.c_str(), log_id(bit.wire), bit.offset);
+ work->set_dirty(std::get<0>(port));
+ }
+ }
+ work->unset_dirty(bit);
+ }
+ }
+
+ if (!work->dirty_cells.empty())
+ {
+ Cell *cell = nullptr;
+ for (auto c : work->dirty_cells)
+ if (cell == nullptr || topoidx.at(cell) < topoidx.at(c))
+ cell = c;
+
+ string hiername = work->log_prefix + "." + log_id(cell);
+
+ if (verbose)
+ log(" Evaluating %s (%s, best of %d).\n", hiername.c_str(), log_id(cell->type), GetSize(work->dirty_cells));
+
+ if (activated_cells.count(hiername))
+ reactivated_cells.insert(hiername);
+ activated_cells.insert(hiername);
+
+ eval_cell(work, cell);
+ work->unset_dirty(cell);
+ }
+ }
+
+ for (auto &child : work->children)
+ eval_dirty(child.second);
+ }
+ }
+
+ void eval_sticky_dirty(HierDirtyFlags *work)
+ {
+ Module *mod = work->module;
+
+ for (Wire *w : mod->wires())
+ for (SigBit bit : SigSpec(w))
+ {
+ SigBit canonical_bit = sigmaps.at(mod)(bit);
+
+ if (canonical_bit == bit)
+ continue;
+
+ if (work->sticky_dirty_bits.count(canonical_bit) == 0)
+ continue;
+
+ if (bit.wire == nullptr || canonical_bit.wire == nullptr)
+ continue;
+
+ funct_declarations.push_back(util_set_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset,
+ util_get_bit(work->prefix + cid(canonical_bit.wire->name), canonical_bit.wire->width, canonical_bit.offset).c_str()));
+
+ if (verbose)
+ log(" Propagating alias %s.%s[%d] -> %s.%s[%d].\n",
+ work->log_prefix.c_str(), log_id(canonical_bit.wire), canonical_bit.offset,
+ work->log_prefix.c_str(), log_id(bit.wire), bit.offset);
+ }
+
+ work->sticky_dirty_bits.clear();
+
+ for (auto &child : work->children)
+ eval_sticky_dirty(child.second);
+ }
+
+ void make_func(HierDirtyFlags *work, const string &func_name, const vector<string> &preamble)
+ {
+ log("Generating function %s():\n", func_name.c_str());
+
+ activated_cells.clear();
+ reactivated_cells.clear();
+
+ funct_declarations.push_back("");
+ funct_declarations.push_back(stringf("static void %s(struct %s_state_t *state)", func_name.c_str(), cid(work->module->name).c_str()));
+ funct_declarations.push_back("{");
+ for (auto &line : preamble)
+ funct_declarations.push_back(line);
+ eval_dirty(work);
+ eval_sticky_dirty(work);
+ funct_declarations.push_back("}");
+
+ log(" Activated %d cells (%d activated more than once).\n", GetSize(activated_cells), GetSize(reactivated_cells));
+ }
+
+ void eval_init(HierDirtyFlags *work, vector<string> &preamble)
+ {
+ Module *module = work->module;
+
+ for (Wire *w : module->wires())
+ {
+ if (w->attributes.count("\\init"))
+ {
+ SigSpec sig = sigmaps.at(module)(w);
+ Const val = w->attributes.at("\\init");
+ val.bits.resize(GetSize(sig), State::Sx);
+
+ for (int i = 0; i < GetSize(sig); i++)
+ if (val[i] == State::S0 || val[i] == State::S1) {
+ SigBit bit = sig[i];
+ preamble.push_back(util_set_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset, val == State::S1 ? "true" : "false"));
+ work->set_dirty(bit);
+ }
+ }
+
+ for (SigBit bit : SigSpec(w))
+ {
+ SigBit val = sigmaps.at(module)(bit);
+
+ if (val == State::S0 || val == State::S1)
+ preamble.push_back(util_set_bit(work->prefix + cid(bit.wire->name), bit.wire->width, bit.offset, val == State::S1 ? "true" : "false"));
+
+ if (driven_bits.at(module).count(val) == 0)
+ work->set_dirty(val);
+ }
+ }
+
+ work->set_dirty(State::S0);
+ work->set_dirty(State::S1);
+
+ for (auto &child : work->children)
+ eval_init(child.second, preamble);
+ }
+
+ void make_init_func(HierDirtyFlags *work)
+ {
+ vector<string> preamble;
+ eval_init(work, preamble);
+ make_func(work, cid(work->module->name) + "_init", preamble);
+ }
+
+ void make_eval_func(HierDirtyFlags *work)
+ {
+ Module *mod = work->module;
+ vector<string> preamble;
+
+ for (Wire *w : mod->wires()) {
+ if (w->port_input)
+ for (SigBit bit : sigmaps.at(mod)(w))
+ work->set_dirty(bit);
+ }
+
+ make_func(work, cid(work->module->name) + "_eval", preamble);
+ }
+
+ void make_tick_func(HierDirtyFlags* /* work */)
+ {
+ // FIXME
+ }
+
+ void run(Module *mod)
+ {
+ create_module_struct(mod);
+
+ HierDirtyFlags work(mod, IdString(), nullptr, "state->", log_id(mod->name));
+
+ make_init_func(&work);
+ make_eval_func(&work);
+ make_tick_func(&work);
+ }
+
+ void write(std::ostream &f)
+ {
+ f << "#include <stdint.h>" << std::endl;
+ f << "#include <stdbool.h>" << std::endl;
+
+ for (auto &line : signal_declarations)
+ f << line << std::endl;
+
+ for (auto &line : util_declarations)
+ f << line << std::endl;
+
+ for (auto &line : struct_declarations)
+ f << line << std::endl;
+
+ for (auto &line : funct_declarations)
+ f << line << std::endl;
+ }
+};
+
+struct SimplecBackend : public Backend {
+ SimplecBackend() : Backend("simplec", "convert design to simple C code") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" write_simplec [options] [filename]\n");
+ log("\n");
+ log("Write simple C code for simulating the design. The C code writen can be used to\n");
+ log("simulate the design in a C environment, but the purpose of this command is to\n");
+ log("generate code that works well with C-based formal verification.\n");
+ log("\n");
+ log(" -verbose\n");
+ log(" this will print the recursive walk used to export the modules.\n");
+ log("\n");
+ log(" -i8, -i16, -i32, -i64\n");
+ log(" set the maximum integer bit width to use in the generated code.\n");
+ log("\n");
+ log("THIS COMMAND IS UNDER CONSTRUCTION\n");
+ log("\n");
+ }
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ reserved_cids.clear();
+ id2cid.clear();
+
+ SimplecWorker worker(design);
+
+ log_header(design, "Executing SIMPLEC backend.\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-verbose") {
+ worker.verbose = true;
+ continue;
+ }
+ if (args[argidx] == "-i8") {
+ worker.max_uintsize = 8;
+ continue;
+ }
+ if (args[argidx] == "-i16") {
+ worker.max_uintsize = 16;
+ continue;
+ }
+ if (args[argidx] == "-i32") {
+ worker.max_uintsize = 32;
+ continue;
+ }
+ if (args[argidx] == "-i64") {
+ worker.max_uintsize = 64;
+ continue;
+ }
+ break;
+ }
+ extra_args(f, filename, args, argidx);
+
+ Module *topmod = design->top_module();
+
+ if (topmod == nullptr)
+ log_error("Current design has no top module.\n");
+
+ worker.run(topmod);
+ worker.write(*f);
+ }
+} SimplecBackend;
+
+PRIVATE_NAMESPACE_END
diff --git a/backends/simplec/test00.sh b/backends/simplec/test00.sh
new file mode 100644
index 00000000..ede75727
--- /dev/null
+++ b/backends/simplec/test00.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+set -ex
+../../yosys -p 'synth -top test; write_simplec -verbose -i8 test00_uut.c' test00_uut.v
+clang -o test00_tb test00_tb.c
+./test00_tb
diff --git a/backends/simplec/test00_tb.c b/backends/simplec/test00_tb.c
new file mode 100644
index 00000000..7fac4826
--- /dev/null
+++ b/backends/simplec/test00_tb.c
@@ -0,0 +1,93 @@
+#include <stdio.h>
+#include <assert.h>
+#include "test00_uut.c"
+
+uint32_t xorshift32()
+{
+ static uint32_t x32 = 314159265;
+ x32 ^= x32 << 13;
+ x32 ^= x32 >> 17;
+ x32 ^= x32 << 5;
+ return x32;
+}
+
+int main()
+{
+ struct test_state_t state;
+ uint32_t a, b, c, x, y, z, w;
+ bool first_eval = true;
+
+ for (int i = 0; i < 10; i++)
+ {
+ a = xorshift32();
+ b = xorshift32();
+ c = xorshift32();
+
+ x = (a & b) | c;
+ y = a & (b | c);
+ z = a ^ b ^ c;
+ w = z;
+
+ state.a.value_7_0 = a;
+ state.a.value_15_8 = a >> 8;
+ state.a.value_23_16 = a >> 16;
+ state.a.value_31_24 = a >> 24;
+
+ state.b.value_7_0 = b;
+ state.b.value_15_8 = b >> 8;
+ state.b.value_23_16 = b >> 16;
+ state.b.value_31_24 = b >> 24;
+
+ state.c.value_7_0 = c;
+ state.c.value_15_8 = c >> 8;
+ state.c.value_23_16 = c >> 16;
+ state.c.value_31_24 = c >> 24;
+
+ if (first_eval) {
+ first_eval = false;
+ test_init(&state);
+ } else {
+ test_eval(&state);
+ }
+
+ uint32_t uut_x = 0;
+ uut_x |= (uint32_t)state.x.value_7_0;
+ uut_x |= (uint32_t)state.x.value_15_8 << 8;
+ uut_x |= (uint32_t)state.x.value_23_16 << 16;
+ uut_x |= (uint32_t)state.x.value_31_24 << 24;
+
+ uint32_t uut_y = 0;
+ uut_y |= (uint32_t)state.y.value_7_0;
+ uut_y |= (uint32_t)state.y.value_15_8 << 8;
+ uut_y |= (uint32_t)state.y.value_23_16 << 16;
+ uut_y |= (uint32_t)state.y.value_31_24 << 24;
+
+ uint32_t uut_z = 0;
+ uut_z |= (uint32_t)state.z.value_7_0;
+ uut_z |= (uint32_t)state.z.value_15_8 << 8;
+ uut_z |= (uint32_t)state.z.value_23_16 << 16;
+ uut_z |= (uint32_t)state.z.value_31_24 << 24;
+
+ uint32_t uut_w = 0;
+ uut_w |= (uint32_t)state.w.value_7_0;
+ uut_w |= (uint32_t)state.w.value_15_8 << 8;
+ uut_w |= (uint32_t)state.w.value_23_16 << 16;
+ uut_w |= (uint32_t)state.w.value_31_24 << 24;
+
+ printf("---\n");
+ printf("A: 0x%08x\n", a);
+ printf("B: 0x%08x\n", b);
+ printf("C: 0x%08x\n", c);
+ printf("X: 0x%08x 0x%08x\n", x, uut_x);
+ printf("Y: 0x%08x 0x%08x\n", y, uut_y);
+ printf("Z: 0x%08x 0x%08x\n", z, uut_z);
+ printf("W: 0x%08x 0x%08x\n", w, uut_w);
+
+ assert(x == uut_x);
+ assert(y == uut_y);
+ assert(z == uut_z);
+ assert(w == uut_w);
+ }
+
+ return 0;
+}
diff --git a/backends/simplec/test00_uut.v b/backends/simplec/test00_uut.v
new file mode 100644
index 00000000..744dbe9e
--- /dev/null
+++ b/backends/simplec/test00_uut.v
@@ -0,0 +1,14 @@
+module test(input [31:0] a, b, c, output [31:0] x, y, z, w);
+ unit_x unit_x_inst (.a(a), .b(b), .c(c), .x(x));
+ unit_y unit_y_inst (.a(a), .b(b), .c(c), .y(y));
+ assign z = a ^ b ^ c, w = z;
+endmodule
+
+module unit_x(input [31:0] a, b, c, output [31:0] x);
+ assign x = (a & b) | c;
+endmodule
+
+module unit_y(input [31:0] a, b, c, output [31:0] y);
+ assign y = a & (b | c);
+endmodule
+
diff --git a/backends/smt2/Makefile.inc b/backends/smt2/Makefile.inc
index eacda273..dce82f01 100644
--- a/backends/smt2/Makefile.inc
+++ b/backends/smt2/Makefile.inc
@@ -6,7 +6,7 @@ ifneq ($(CONFIG),emcc)
TARGETS += yosys-smtbmc
yosys-smtbmc: backends/smt2/smtbmc.py
- $(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(__file__) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' < $< > $@.new
+ $(P) sed 's|##yosys-sys-path##|sys.path += [os.path.dirname(os.path.realpath(__file__)) + p for p in ["/share/python3", "/../share/yosys/python3"]]|;' < $< > $@.new
$(Q) chmod +x $@.new
$(Q) mv $@.new $@
diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc
index ddac6900..e2777ae0 100644
--- a/backends/smt2/smt2.cc
+++ b/backends/smt2/smt2.cc
@@ -32,14 +32,18 @@ struct Smt2Worker
CellTypes ct;
SigMap sigmap;
RTLIL::Module *module;
- bool bvmode, memmode, wiresmode, verbose;
- int idcounter;
+ bool bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode;
+ dict<IdString, int> &mod_stbv_width;
+ int idcounter = 0, statebv_width = 0;
- std::vector<std::string> decls, trans, hier;
+ std::vector<std::string> decls, trans, hier, dtmembers;
std::map<RTLIL::SigBit, RTLIL::Cell*> bit_driver;
std::set<RTLIL::Cell*> exported_cells, hiercells, hiercells_queue;
pool<Cell*> recursive_cells, registers;
+ pool<SigBit> clock_posedge, clock_negedge;
+ vector<string> ex_state_eq, ex_input_eq;
+
std::map<RTLIL::SigBit, std::pair<int, int>> fcache;
std::map<Cell*, int> memarrays;
std::map<int, int> bvsizes;
@@ -63,17 +67,64 @@ struct Smt2Worker
return get_id(obj->name);
}
- Smt2Worker(RTLIL::Module *module, bool bvmode, bool memmode, bool wiresmode, bool verbose) :
- ct(module->design), sigmap(module), module(module), bvmode(bvmode), memmode(memmode),
- wiresmode(wiresmode), verbose(verbose), idcounter(0)
+ void makebits(std::string name, int width = 0, std::string comment = std::string())
+ {
+ std::string decl_str;
+
+ if (statebv)
+ {
+ if (width == 0) {
+ decl_str = stringf("(define-fun |%s| ((state |%s_s|)) Bool (= ((_ extract %d %d) state) #b1))", name.c_str(), get_id(module), statebv_width, statebv_width);
+ statebv_width += 1;
+ } else {
+ decl_str = stringf("(define-fun |%s| ((state |%s_s|)) (_ BitVec %d) ((_ extract %d %d) state))", name.c_str(), get_id(module), width, statebv_width+width-1, statebv_width);
+ statebv_width += width;
+ }
+ }
+ else if (statedt)
+ {
+ if (width == 0) {
+ decl_str = stringf(" (|%s| Bool)", name.c_str());
+ } else {
+ decl_str = stringf(" (|%s| (_ BitVec %d))", name.c_str(), width);
+ }
+ }
+ else
+ {
+ if (width == 0) {
+ decl_str = stringf("(declare-fun |%s| (|%s_s|) Bool)", name.c_str(), get_id(module));
+ } else {
+ decl_str = stringf("(declare-fun |%s| (|%s_s|) (_ BitVec %d))", name.c_str(), get_id(module), width);
+ }
+ }
+
+ if (!comment.empty())
+ decl_str += " ; " + comment;
+
+ if (statedt)
+ dtmembers.push_back(decl_str + "\n");
+ else
+ decls.push_back(decl_str + "\n");
+ }
+
+ Smt2Worker(RTLIL::Module *module, bool bvmode, bool memmode, bool wiresmode, bool verbose, bool statebv, bool statedt, bool forallmode,
+ dict<IdString, int> &mod_stbv_width, dict<IdString, dict<IdString, pair<bool, bool>>> &mod_clk_cache) :
+ ct(module->design), sigmap(module), module(module), bvmode(bvmode), memmode(memmode), wiresmode(wiresmode),
+ verbose(verbose), statebv(statebv), statedt(statedt), forallmode(forallmode), mod_stbv_width(mod_stbv_width)
{
- decls.push_back(stringf("(declare-sort |%s_s| 0)\n", get_id(module)));
- decls.push_back(stringf("(declare-fun |%s_is| (|%s_s|) Bool)\n", get_id(module), get_id(module)));
+ pool<SigBit> noclock;
+
+ makebits(stringf("%s_is", get_id(module)));
for (auto cell : module->cells())
- for (auto &conn : cell->connections()) {
+ for (auto &conn : cell->connections())
+ {
+ if (GetSize(conn.second) == 0)
+ continue;
+
bool is_input = ct.cell_input(cell->type, conn.first);
bool is_output = ct.cell_output(cell->type, conn.first);
+
if (is_output && !is_input)
for (auto bit : sigmap(conn.second)) {
if (bit_driver.count(bit))
@@ -83,6 +134,66 @@ struct Smt2Worker
else if (is_output || !is_input)
log_error("Unsupported or unknown directionality on port %s of cell %s.%s (%s).\n",
log_id(conn.first), log_id(module), log_id(cell), log_id(cell->type));
+
+ if (cell->type.in("$mem") && conn.first.in("\\RD_CLK", "\\WR_CLK"))
+ {
+ SigSpec clk = sigmap(conn.second);
+ for (int i = 0; i < GetSize(clk); i++)
+ {
+ if (clk[i].wire == nullptr)
+ continue;
+
+ if (cell->getParam(conn.first == "\\RD_CLK" ? "\\RD_CLK_ENABLE" : "\\WR_CLK_ENABLE")[i] != State::S1)
+ continue;
+
+ if (cell->getParam(conn.first == "\\RD_CLK" ? "\\RD_CLK_POLARITY" : "\\WR_CLK_POLARITY")[i] == State::S1)
+ clock_posedge.insert(clk[i]);
+ else
+ clock_negedge.insert(clk[i]);
+ }
+ }
+ else
+ if (cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_") && conn.first.in("\\CLK", "\\C"))
+ {
+ bool posedge = (cell->type == "$_DFF_N_") || (cell->type == "$dff" && cell->getParam("\\CLK_POLARITY").as_bool());
+ for (auto bit : sigmap(conn.second)) {
+ if (posedge)
+ clock_posedge.insert(bit);
+ else
+ clock_negedge.insert(bit);
+ }
+ }
+ else
+ if (mod_clk_cache.count(cell->type) && mod_clk_cache.at(cell->type).count(conn.first))
+ {
+ for (auto bit : sigmap(conn.second)) {
+ if (mod_clk_cache.at(cell->type).at(conn.first).first)
+ clock_posedge.insert(bit);
+ if (mod_clk_cache.at(cell->type).at(conn.first).second)
+ clock_negedge.insert(bit);
+ }
+ }
+ else
+ {
+ for (auto bit : sigmap(conn.second))
+ noclock.insert(bit);
+ }
+ }
+
+ for (auto bit : noclock) {
+ clock_posedge.erase(bit);
+ clock_negedge.erase(bit);
+ }
+
+ for (auto wire : module->wires())
+ {
+ if (!wire->port_input || GetSize(wire) != 1)
+ continue;
+ SigBit bit = sigmap(wire);
+ if (clock_posedge.count(bit))
+ mod_clk_cache[module->name][wire->name].first = true;
+ if (clock_negedge.count(bit))
+ mod_clk_cache[module->name][wire->name].second = true;
}
}
@@ -162,8 +273,7 @@ struct Smt2Worker
if (fcache.count(bit) == 0) {
if (verbose) log("%*s-> external bool: %s\n", 2+2*GetSize(recursive_cells), "",
log_signal(bit));
- decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) Bool) ; %s\n",
- get_id(module), idcounter, get_id(module), log_signal(bit)));
+ makebits(stringf("%s#%d", get_id(module), idcounter), 0, log_signal(bit));
register_bool(bit, idcounter++);
}
@@ -237,8 +347,7 @@ struct Smt2Worker
log_signal(sig.extract(i, j)));
for (auto bit : sig.extract(i, j))
log_assert(bit_driver.count(bit) == 0);
- decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) (_ BitVec %d)) ; %s\n",
- get_id(module), idcounter, get_id(module), j, log_signal(sig.extract(i, j))));
+ makebits(stringf("%s#%d", get_id(module), idcounter), j, log_signal(sig.extract(i, j)));
subexpr.push_back(stringf("(|%s#%d| %s)", get_id(module), idcounter, state_name));
register_bv(sig.extract(i, j), idcounter++);
}
@@ -288,7 +397,8 @@ struct Smt2Worker
if (type == 's' || type == 'd' || type == 'b') {
width = max(width, GetSize(cell->getPort("\\A")));
- width = max(width, GetSize(cell->getPort("\\B")));
+ if (cell->hasPort("\\B"))
+ width = max(width, GetSize(cell->getPort("\\B")));
}
if (cell->hasPort("\\A")) {
@@ -382,8 +492,7 @@ struct Smt2Worker
if (cell->type.in("$_FF_", "$_DFF_P_", "$_DFF_N_"))
{
registers.insert(cell);
- decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) Bool) ; %s\n",
- get_id(module), idcounter, get_id(module), log_signal(cell->getPort("\\Q"))));
+ makebits(stringf("%s#%d", get_id(module), idcounter), 0, log_signal(cell->getPort("\\Q")));
register_bool(cell->getPort("\\Q"), idcounter++);
recursive_cells.erase(cell);
return;
@@ -397,6 +506,8 @@ struct Smt2Worker
if (cell->type == "$_NOR_") return export_gate(cell, "(not (or A B))");
if (cell->type == "$_XOR_") return export_gate(cell, "(xor A B)");
if (cell->type == "$_XNOR_") return export_gate(cell, "(not (xor A B))");
+ if (cell->type == "$_ANDNOT_") return export_gate(cell, "(and A (not B))");
+ if (cell->type == "$_ORNOT_") return export_gate(cell, "(or A (not B))");
if (cell->type == "$_MUX_") return export_gate(cell, "(ite S B A)");
if (cell->type == "$_AOI3_") return export_gate(cell, "(not (or (and A B) C))");
if (cell->type == "$_OAI3_") return export_gate(cell, "(not (and (or A B) C))");
@@ -410,20 +521,22 @@ struct Smt2Worker
if (cell->type.in("$ff", "$dff"))
{
registers.insert(cell);
- decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) (_ BitVec %d)) ; %s\n",
- get_id(module), idcounter, get_id(module), GetSize(cell->getPort("\\Q")), log_signal(cell->getPort("\\Q"))));
+ makebits(stringf("%s#%d", get_id(module), idcounter), GetSize(cell->getPort("\\Q")), log_signal(cell->getPort("\\Q")));
register_bv(cell->getPort("\\Q"), idcounter++);
recursive_cells.erase(cell);
return;
}
- if (cell->type.in("$anyconst", "$anyseq"))
+ if (cell->type.in("$anyconst", "$anyseq", "$allconst", "$allseq"))
{
registers.insert(cell);
- decls.push_back(stringf("; yosys-smt2-%s %s#%d %s\n", cell->type.c_str() + 1, get_id(module), idcounter,
- cell->attributes.count("\\src") ? cell->attributes.at("\\src").decode_string().c_str() : get_id(cell)));
- decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) (_ BitVec %d)) ; %s\n",
- get_id(module), idcounter, get_id(module), GetSize(cell->getPort("\\Y")), log_signal(cell->getPort("\\Y"))));
+ string infostr = cell->attributes.count("\\src") ? cell->attributes.at("\\src").decode_string().c_str() : get_id(cell);
+ if (cell->attributes.count("\\reg"))
+ infostr += " " + cell->attributes.at("\\reg").decode_string();
+ decls.push_back(stringf("; yosys-smt2-%s %s#%d %d %s\n", cell->type.c_str() + 1, get_id(module), idcounter, GetSize(cell->getPort("\\Y")), infostr.c_str()));
+ makebits(stringf("%s#%d", get_id(module), idcounter), GetSize(cell->getPort("\\Y")), log_signal(cell->getPort("\\Y")));
+ if (cell->type == "$anyseq")
+ ex_input_eq.push_back(stringf(" (= (|%s#%d| state) (|%s#%d| other_state))", get_id(module), idcounter, get_id(module), idcounter));
register_bv(cell->getPort("\\Y"), idcounter++);
recursive_cells.erase(cell);
return;
@@ -467,6 +580,13 @@ struct Smt2Worker
if (cell->type == "$div") return export_bvop(cell, "(bvUdiv A B)", 'd');
if (cell->type == "$mod") return export_bvop(cell, "(bvUrem A B)", 'd');
+ if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool") &&
+ 2*GetSize(cell->getPort("\\A").chunks()) < GetSize(cell->getPort("\\A"))) {
+ bool is_and = cell->type == "$reduce_and";
+ string bits(GetSize(cell->getPort("\\A")), is_and ? '1' : '0');
+ return export_bvop(cell, stringf("(%s A #b%s)", is_and ? "=" : "distinct", bits.c_str()), 'b');
+ }
+
if (cell->type == "$reduce_and") return export_reduce(cell, "(and A)", true);
if (cell->type == "$reduce_or") return export_reduce(cell, "(or A)", false);
if (cell->type == "$reduce_xor") return export_reduce(cell, "(xor A)", false);
@@ -513,30 +633,97 @@ struct Smt2Worker
int abits = cell->getParam("\\ABITS").as_int();
int width = cell->getParam("\\WIDTH").as_int();
int rd_ports = cell->getParam("\\RD_PORTS").as_int();
+ int wr_ports = cell->getParam("\\WR_PORTS").as_int();
- decls.push_back(stringf("(declare-fun |%s#%d#0| (|%s_s|) (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n",
- get_id(module), arrayid, get_id(module), abits, width, get_id(cell)));
+ bool async_read = false;
+ if (!cell->getParam("\\WR_CLK_ENABLE").is_fully_ones()) {
+ if (!cell->getParam("\\WR_CLK_ENABLE").is_fully_zero())
+ log_error("Memory %s.%s has mixed clocked/nonclocked write ports. This is not supported by \"write_smt2\".\n", log_id(cell), log_id(module));
+ async_read = true;
+ }
- decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d\n", get_id(cell), abits, width, rd_ports));
- decls.push_back(stringf("(define-fun |%s_m %s| ((state |%s_s|)) (Array (_ BitVec %d) (_ BitVec %d)) (|%s#%d#0| state))\n",
- get_id(module), get_id(cell), get_id(module), abits, width, get_id(module), arrayid));
+ decls.push_back(stringf("; yosys-smt2-memory %s %d %d %d %d %s\n", get_id(cell), abits, width, rd_ports, wr_ports, async_read ? "async" : "sync"));
- for (int i = 0; i < rd_ports; i++)
+ string memstate;
+ if (async_read) {
+ memstate = stringf("%s#%d#final", get_id(module), arrayid);
+ } else {
+ memstate = stringf("%s#%d#0", get_id(module), arrayid);
+ }
+
+ if (statebv)
{
- SigSpec addr_sig = cell->getPort("\\RD_ADDR").extract(abits*i, abits);
- SigSpec data_sig = cell->getPort("\\RD_DATA").extract(width*i, width);
- std::string addr = get_bv(addr_sig);
+ int mem_size = cell->getParam("\\SIZE").as_int();
+ int mem_offset = cell->getParam("\\OFFSET").as_int();
+
+ makebits(memstate, width*mem_size, get_id(cell));
+ decls.push_back(stringf("(define-fun |%s_m %s| ((state |%s_s|)) (_ BitVec %d) (|%s| state))\n",
+ get_id(module), get_id(cell), get_id(module), width*mem_size, memstate.c_str()));
+
+ for (int i = 0; i < rd_ports; i++)
+ {
+ SigSpec addr_sig = cell->getPort("\\RD_ADDR").extract(abits*i, abits);
+ SigSpec data_sig = cell->getPort("\\RD_DATA").extract(width*i, width);
+ std::string addr = get_bv(addr_sig);
+
+ if (cell->getParam("\\RD_CLK_ENABLE").extract(i).as_bool())
+ log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! "
+ "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(data_sig), log_id(cell), log_id(module));
+
+ decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
+ get_id(module), i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
- if (cell->getParam("\\RD_CLK_ENABLE").extract(i).as_bool())
- log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! "
- "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(data_sig), log_id(cell), log_id(module));
+ std::string read_expr = "#b";
+ for (int k = 0; k < width; k++)
+ read_expr += "0";
- decls.push_back(stringf("(define-fun |%s_m:%d %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
- get_id(module), i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
+ for (int k = 0; k < mem_size; k++)
+ read_expr = stringf("(ite (= (|%s_m:R%dA %s| state) #b%s) ((_ extract %d %d) (|%s| state))\n %s)",
+ get_id(module), i, get_id(cell), Const(k+mem_offset, abits).as_string().c_str(),
+ width*(k+1)-1, width*k, memstate.c_str(), read_expr.c_str());
- decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) (select (|%s#%d#0| state) %s)) ; %s\n",
- get_id(module), idcounter, get_id(module), width, get_id(module), arrayid, addr.c_str(), log_signal(data_sig)));
- register_bv(data_sig, idcounter++);
+ decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d)\n %s) ; %s\n",
+ get_id(module), idcounter, get_id(module), width, read_expr.c_str(), log_signal(data_sig)));
+
+ decls.push_back(stringf("(define-fun |%s_m:R%dD %s| ((state |%s_s|)) (_ BitVec %d) (|%s#%d| state))\n",
+ get_id(module), i, get_id(cell), get_id(module), width, get_id(module), idcounter));
+
+ register_bv(data_sig, idcounter++);
+ }
+ }
+ else
+ {
+ if (statedt)
+ dtmembers.push_back(stringf(" (|%s| (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n",
+ memstate.c_str(), abits, width, get_id(cell)));
+ else
+ decls.push_back(stringf("(declare-fun |%s| (|%s_s|) (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n",
+ memstate.c_str(), get_id(module), abits, width, get_id(cell)));
+
+ decls.push_back(stringf("(define-fun |%s_m %s| ((state |%s_s|)) (Array (_ BitVec %d) (_ BitVec %d)) (|%s| state))\n",
+ get_id(module), get_id(cell), get_id(module), abits, width, memstate.c_str()));
+
+ for (int i = 0; i < rd_ports; i++)
+ {
+ SigSpec addr_sig = cell->getPort("\\RD_ADDR").extract(abits*i, abits);
+ SigSpec data_sig = cell->getPort("\\RD_DATA").extract(width*i, width);
+ std::string addr = get_bv(addr_sig);
+
+ if (cell->getParam("\\RD_CLK_ENABLE").extract(i).as_bool())
+ log_error("Read port %d (%s) of memory %s.%s is clocked. This is not supported by \"write_smt2\"! "
+ "Call \"memory\" with -nordff to avoid this error.\n", i, log_signal(data_sig), log_id(cell), log_id(module));
+
+ decls.push_back(stringf("(define-fun |%s_m:R%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
+ get_id(module), i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
+
+ decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) (_ BitVec %d) (select (|%s| state) (|%s_m:R%dA %s| state))) ; %s\n",
+ get_id(module), idcounter, get_id(module), width, memstate.c_str(), get_id(module), i, get_id(cell), log_signal(data_sig)));
+
+ decls.push_back(stringf("(define-fun |%s_m:R%dD %s| ((state |%s_s|)) (_ BitVec %d) (|%s#%d| state))\n",
+ get_id(module), i, get_id(cell), get_id(module), width, get_id(module), idcounter));
+
+ register_bv(data_sig, idcounter++);
+ }
}
registers.insert(cell);
@@ -553,32 +740,38 @@ struct Smt2Worker
for (auto &conn : cell->connections())
{
+ if (GetSize(conn.second) == 0)
+ continue;
+
Wire *w = m->wire(conn.first);
SigSpec sig = sigmap(conn.second);
if (w->port_output && !w->port_input) {
if (GetSize(w) > 1) {
if (bvmode) {
- decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) (_ BitVec %d)) ; %s\n",
- get_id(module), idcounter, get_id(module), GetSize(w), log_signal(sig)));
+ makebits(stringf("%s#%d", get_id(module), idcounter), GetSize(w), log_signal(sig));
register_bv(sig, idcounter++);
} else {
for (int i = 0; i < GetSize(w); i++) {
- decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) Bool) ; %s\n",
- get_id(module), idcounter, get_id(module), log_signal(sig[i])));
+ makebits(stringf("%s#%d", get_id(module), idcounter), 0, log_signal(sig[i]));
register_bool(sig[i], idcounter++);
}
}
} else {
- decls.push_back(stringf("(declare-fun |%s#%d| (|%s_s|) Bool) ; %s\n",
- get_id(module), idcounter, get_id(module), log_signal(sig)));
+ makebits(stringf("%s#%d", get_id(module), idcounter), 0, log_signal(sig));
register_bool(sig, idcounter++);
}
}
}
- decls.push_back(stringf("(declare-fun |%s_h %s| (|%s_s|) |%s_s|)\n",
- get_id(module), get_id(cell->name), get_id(module), get_id(cell->type)));
+ if (statebv)
+ makebits(stringf("%s_h %s", get_id(module), get_id(cell->name)), mod_stbv_width.at(cell->type));
+ else if (statedt)
+ dtmembers.push_back(stringf(" (|%s_h %s| |%s_s|)\n",
+ get_id(module), get_id(cell->name), get_id(cell->type)));
+ else
+ decls.push_back(stringf("(declare-fun |%s_h %s| (|%s_s|) |%s_s|)\n",
+ get_id(module), get_id(cell->name), get_id(module), get_id(cell->type)));
hiercells.insert(cell);
hiercells_queue.insert(cell);
@@ -617,17 +810,30 @@ struct Smt2Worker
decls.push_back(stringf("; yosys-smt2-register %s %d\n", get_id(wire), wire->width));
if (wire->get_bool_attribute("\\keep") || (wiresmode && wire->name[0] == '\\'))
decls.push_back(stringf("; yosys-smt2-wire %s %d\n", get_id(wire), wire->width));
+ if (GetSize(wire) == 1 && (clock_posedge.count(sig) || clock_negedge.count(sig)))
+ decls.push_back(stringf("; yosys-smt2-clock %s%s%s\n", get_id(wire),
+ clock_posedge.count(sig) ? " posedge" : "", clock_negedge.count(sig) ? " negedge" : ""));
if (bvmode && GetSize(sig) > 1) {
decls.push_back(stringf("(define-fun |%s_n %s| ((state |%s_s|)) (_ BitVec %d) %s)\n",
get_id(module), get_id(wire), get_id(module), GetSize(sig), get_bv(sig).c_str()));
+ if (wire->port_input)
+ ex_input_eq.push_back(stringf(" (= (|%s_n %s| state) (|%s_n %s| other_state))",
+ get_id(module), get_id(wire), get_id(module), get_id(wire)));
} else {
for (int i = 0; i < GetSize(sig); i++)
- if (GetSize(sig) > 1)
+ if (GetSize(sig) > 1) {
decls.push_back(stringf("(define-fun |%s_n %s %d| ((state |%s_s|)) Bool %s)\n",
get_id(module), get_id(wire), i, get_id(module), get_bool(sig[i]).c_str()));
- else
+ if (wire->port_input)
+ ex_input_eq.push_back(stringf(" (= (|%s_n %s %d| state) (|%s_n %s %d| other_state))",
+ get_id(module), get_id(wire), i, get_id(module), get_id(wire), i));
+ } else {
decls.push_back(stringf("(define-fun |%s_n %s| ((state |%s_s|)) Bool %s)\n",
get_id(module), get_id(wire), get_id(module), get_bool(sig[i]).c_str()));
+ if (wire->port_input)
+ ex_input_eq.push_back(stringf(" (= (|%s_n %s| state) (|%s_n %s| other_state))",
+ get_id(module), get_id(wire), get_id(module), get_id(wire)));
+ }
}
}
}
@@ -639,31 +845,104 @@ struct Smt2Worker
if (wire->attributes.count("\\init")) {
RTLIL::SigSpec sig = sigmap(wire);
Const val = wire->attributes.at("\\init");
- val.bits.resize(GetSize(sig));
+ val.bits.resize(GetSize(sig), State::Sx);
if (bvmode && GetSize(sig) > 1) {
- init_list.push_back(stringf("(= %s #b%s) ; %s", get_bv(sig).c_str(), val.as_string().c_str(), get_id(wire)));
+ Const mask(State::S1, GetSize(sig));
+ bool use_mask = false;
+ for (int i = 0; i < GetSize(sig); i++)
+ if (val[i] != State::S0 && val[i] != State::S1) {
+ val[i] = State::S0;
+ mask[i] = State::S0;
+ use_mask = true;
+ }
+ if (use_mask)
+ init_list.push_back(stringf("(= (bvand %s #b%s) #b%s) ; %s", get_bv(sig).c_str(), mask.as_string().c_str(), val.as_string().c_str(), get_id(wire)));
+ else
+ init_list.push_back(stringf("(= %s #b%s) ; %s", get_bv(sig).c_str(), val.as_string().c_str(), get_id(wire)));
} else {
for (int i = 0; i < GetSize(sig); i++)
- init_list.push_back(stringf("(= %s %s) ; %s", get_bool(sig[i]).c_str(), val.bits[i] == State::S1 ? "true" : "false", get_id(wire)));
+ if (val[i] == State::S0 || val[i] == State::S1)
+ init_list.push_back(stringf("(= %s %s) ; %s", get_bool(sig[i]).c_str(), val[i] == State::S1 ? "true" : "false", get_id(wire)));
}
}
if (verbose) log("=> export logic driving asserts\n");
- vector<string> assert_list, assume_list;
+ int assert_id = 0, assume_id = 0, cover_id = 0;
+ vector<string> assert_list, assume_list, cover_list;
+
for (auto cell : module->cells())
- if (cell->type.in("$assert", "$assume")) {
+ {
+ if (cell->type.in("$assert", "$assume", "$cover"))
+ {
+ int &id = cell->type == "$assert" ? assert_id :
+ cell->type == "$assume" ? assume_id :
+ cell->type == "$cover" ? cover_id : *(int*)nullptr;
+
+ char postfix = cell->type == "$assert" ? 'a' :
+ cell->type == "$assume" ? 'u' :
+ cell->type == "$cover" ? 'c' : 0;
+
string name_a = get_bool(cell->getPort("\\A"));
string name_en = get_bool(cell->getPort("\\EN"));
- decls.push_back(stringf("; yosys-smt2-%s %s#%d %s\n", cell->type.c_str() + 1, get_id(module), idcounter,
+ decls.push_back(stringf("; yosys-smt2-%s %d %s\n", cell->type.c_str() + 1, id,
cell->attributes.count("\\src") ? cell->attributes.at("\\src").decode_string().c_str() : get_id(cell)));
- decls.push_back(stringf("(define-fun |%s#%d| ((state |%s_s|)) Bool (or %s (not %s))) ; %s\n",
- get_id(module), idcounter, get_id(module), name_a.c_str(), name_en.c_str(), get_id(cell)));
- if (cell->type == "$assert")
- assert_list.push_back(stringf("(|%s#%d| state)", get_id(module), idcounter++));
+
+ if (cell->type == "$cover")
+ decls.push_back(stringf("(define-fun |%s_%c %d| ((state |%s_s|)) Bool (and %s %s)) ; %s\n",
+ get_id(module), postfix, id, get_id(module), name_a.c_str(), name_en.c_str(), get_id(cell)));
else
- assume_list.push_back(stringf("(|%s#%d| state)", get_id(module), idcounter++));
+ decls.push_back(stringf("(define-fun |%s_%c %d| ((state |%s_s|)) Bool (or %s (not %s))) ; %s\n",
+ get_id(module), postfix, id, get_id(module), name_a.c_str(), name_en.c_str(), get_id(cell)));
+
+ if (cell->type == "$assert")
+ assert_list.push_back(stringf("(|%s_a %d| state)", get_id(module), id));
+ else if (cell->type == "$assume")
+ assume_list.push_back(stringf("(|%s_u %d| state)", get_id(module), id));
+
+ id++;
}
+ }
+
+ if (verbose) log("=> export logic driving hierarchical cells\n");
+
+ for (auto cell : module->cells())
+ if (module->design->module(cell->type) != nullptr)
+ export_cell(cell);
+
+ while (!hiercells_queue.empty())
+ {
+ std::set<RTLIL::Cell*> queue;
+ queue.swap(hiercells_queue);
+
+ for (auto cell : queue)
+ {
+ string cell_state = stringf("(|%s_h %s| state)", get_id(module), get_id(cell->name));
+ Module *m = module->design->module(cell->type);
+ log_assert(m != nullptr);
+
+ hier.push_back(stringf(" (= (|%s_is| state) (|%s_is| %s))\n",
+ get_id(module), get_id(cell->type), cell_state.c_str()));
+
+ for (auto &conn : cell->connections())
+ {
+ if (GetSize(conn.second) == 0)
+ continue;
+
+ Wire *w = m->wire(conn.first);
+ SigSpec sig = sigmap(conn.second);
+
+ if (bvmode || GetSize(w) == 1) {
+ hier.push_back(stringf(" (= %s (|%s_n %s| %s)) ; %s.%s\n", (GetSize(w) > 1 ? get_bv(sig) : get_bool(sig)).c_str(),
+ get_id(cell->type), get_id(w), cell_state.c_str(), get_id(cell->type), get_id(w)));
+ } else {
+ for (int i = 0; i < GetSize(w); i++)
+ hier.push_back(stringf(" (= %s (|%s_n %s %d| %s)) ; %s.%s[%d]\n", get_bool(sig[i]).c_str(),
+ get_id(cell->type), get_id(w), i, cell_state.c_str(), get_id(cell->type), get_id(w), i));
+ }
+ }
+ }
+ }
for (int iter = 1; !registers.empty(); iter++)
{
@@ -679,6 +958,7 @@ struct Smt2Worker
std::string expr_d = get_bool(cell->getPort("\\D"));
std::string expr_q = get_bool(cell->getPort("\\Q"), "next_state");
trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell), log_signal(cell->getPort("\\Q"))));
+ ex_state_eq.push_back(stringf("(= %s %s)", get_bool(cell->getPort("\\Q")).c_str(), get_bool(cell->getPort("\\Q"), "other_state").c_str()));
}
if (cell->type.in("$ff", "$dff"))
@@ -686,13 +966,16 @@ struct Smt2Worker
std::string expr_d = get_bv(cell->getPort("\\D"));
std::string expr_q = get_bv(cell->getPort("\\Q"), "next_state");
trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell), log_signal(cell->getPort("\\Q"))));
+ ex_state_eq.push_back(stringf("(= %s %s)", get_bv(cell->getPort("\\Q")).c_str(), get_bv(cell->getPort("\\Q"), "other_state").c_str()));
}
- if (cell->type == "$anyconst")
+ if (cell->type.in("$anyconst", "$allconst"))
{
std::string expr_d = get_bv(cell->getPort("\\Y"));
std::string expr_q = get_bv(cell->getPort("\\Y"), "next_state");
trans.push_back(stringf(" (= %s %s) ; %s %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell), log_signal(cell->getPort("\\Y"))));
+ if (cell->type == "$anyconst")
+ ex_state_eq.push_back(stringf("(= %s %s)", get_bv(cell->getPort("\\Y")).c_str(), get_bv(cell->getPort("\\Y"), "other_state").c_str()));
}
if (cell->type == "$mem")
@@ -703,24 +986,111 @@ struct Smt2Worker
int width = cell->getParam("\\WIDTH").as_int();
int wr_ports = cell->getParam("\\WR_PORTS").as_int();
- for (int i = 0; i < wr_ports; i++)
+ bool async_read = false;
+ string initial_memstate, final_memstate;
+
+ if (!cell->getParam("\\WR_CLK_ENABLE").is_fully_ones()) {
+ log_assert(cell->getParam("\\WR_CLK_ENABLE").is_fully_zero());
+ async_read = true;
+ initial_memstate = stringf("%s#%d#0", get_id(module), arrayid);
+ final_memstate = stringf("%s#%d#final", get_id(module), arrayid);
+ }
+
+ if (statebv)
+ {
+ int mem_size = cell->getParam("\\SIZE").as_int();
+ int mem_offset = cell->getParam("\\OFFSET").as_int();
+
+ if (async_read) {
+ makebits(final_memstate, width*mem_size, get_id(cell));
+ }
+
+ for (int i = 0; i < wr_ports; i++)
+ {
+ SigSpec addr_sig = cell->getPort("\\WR_ADDR").extract(abits*i, abits);
+ SigSpec data_sig = cell->getPort("\\WR_DATA").extract(width*i, width);
+ SigSpec mask_sig = cell->getPort("\\WR_EN").extract(width*i, width);
+
+ std::string addr = get_bv(addr_sig);
+ std::string data = get_bv(data_sig);
+ std::string mask = get_bv(mask_sig);
+
+ decls.push_back(stringf("(define-fun |%s_m:W%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
+ get_id(module), i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
+ addr = stringf("(|%s_m:W%dA %s| state)", get_id(module), i, get_id(cell));
+
+ decls.push_back(stringf("(define-fun |%s_m:W%dD %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
+ get_id(module), i, get_id(cell), get_id(module), width, data.c_str(), log_signal(data_sig)));
+ data = stringf("(|%s_m:W%dD %s| state)", get_id(module), i, get_id(cell));
+
+ decls.push_back(stringf("(define-fun |%s_m:W%dM %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
+ get_id(module), i, get_id(cell), get_id(module), width, mask.c_str(), log_signal(mask_sig)));
+ mask = stringf("(|%s_m:W%dM %s| state)", get_id(module), i, get_id(cell));
+
+ std::string data_expr;
+
+ for (int k = mem_size-1; k >= 0; k--) {
+ std::string new_data = stringf("(bvor (bvand %s %s) (bvand ((_ extract %d %d) (|%s#%d#%d| state)) (bvnot %s)))",
+ data.c_str(), mask.c_str(), width*(k+1)-1, width*k, get_id(module), arrayid, i, mask.c_str());
+ data_expr += stringf("\n (ite (= %s #b%s) %s ((_ extract %d %d) (|%s#%d#%d| state)))",
+ addr.c_str(), Const(k+mem_offset, abits).as_string().c_str(), new_data.c_str(),
+ width*(k+1)-1, width*k, get_id(module), arrayid, i);
+ }
+
+ decls.push_back(stringf("(define-fun |%s#%d#%d| ((state |%s_s|)) (_ BitVec %d) (concat%s)) ; %s\n",
+ get_id(module), arrayid, i+1, get_id(module), width*mem_size, data_expr.c_str(), get_id(cell)));
+ }
+ }
+ else
{
- std::string addr = get_bv(cell->getPort("\\WR_ADDR").extract(abits*i, abits));
- std::string data = get_bv(cell->getPort("\\WR_DATA").extract(width*i, width));
- std::string mask = get_bv(cell->getPort("\\WR_EN").extract(width*i, width));
+ if (async_read) {
+ if (statedt)
+ dtmembers.push_back(stringf(" (|%s| (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n",
+ initial_memstate.c_str(), abits, width, get_id(cell)));
+ else
+ decls.push_back(stringf("(declare-fun |%s| (|%s_s|) (Array (_ BitVec %d) (_ BitVec %d))) ; %s\n",
+ initial_memstate.c_str(), get_id(module), abits, width, get_id(cell)));
+ }
+
+ for (int i = 0; i < wr_ports; i++)
+ {
+ SigSpec addr_sig = cell->getPort("\\WR_ADDR").extract(abits*i, abits);
+ SigSpec data_sig = cell->getPort("\\WR_DATA").extract(width*i, width);
+ SigSpec mask_sig = cell->getPort("\\WR_EN").extract(width*i, width);
+
+ std::string addr = get_bv(addr_sig);
+ std::string data = get_bv(data_sig);
+ std::string mask = get_bv(mask_sig);
+
+ decls.push_back(stringf("(define-fun |%s_m:W%dA %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
+ get_id(module), i, get_id(cell), get_id(module), abits, addr.c_str(), log_signal(addr_sig)));
+ addr = stringf("(|%s_m:W%dA %s| state)", get_id(module), i, get_id(cell));
+
+ decls.push_back(stringf("(define-fun |%s_m:W%dD %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
+ get_id(module), i, get_id(cell), get_id(module), width, data.c_str(), log_signal(data_sig)));
+ data = stringf("(|%s_m:W%dD %s| state)", get_id(module), i, get_id(cell));
+
+ decls.push_back(stringf("(define-fun |%s_m:W%dM %s| ((state |%s_s|)) (_ BitVec %d) %s) ; %s\n",
+ get_id(module), i, get_id(cell), get_id(module), width, mask.c_str(), log_signal(mask_sig)));
+ mask = stringf("(|%s_m:W%dM %s| state)", get_id(module), i, get_id(cell));
- data = stringf("(bvor (bvand %s %s) (bvand (select (|%s#%d#%d| state) %s) (bvnot %s)))",
- data.c_str(), mask.c_str(), get_id(module), arrayid, i, addr.c_str(), mask.c_str());
+ data = stringf("(bvor (bvand %s %s) (bvand (select (|%s#%d#%d| state) %s) (bvnot %s)))",
+ data.c_str(), mask.c_str(), get_id(module), arrayid, i, addr.c_str(), mask.c_str());
- decls.push_back(stringf("(define-fun |%s#%d#%d| ((state |%s_s|)) (Array (_ BitVec %d) (_ BitVec %d)) "
- "(store (|%s#%d#%d| state) %s %s)) ; %s\n",
- get_id(module), arrayid, i+1, get_id(module), abits, width,
- get_id(module), arrayid, i, addr.c_str(), data.c_str(), get_id(cell)));
+ decls.push_back(stringf("(define-fun |%s#%d#%d| ((state |%s_s|)) (Array (_ BitVec %d) (_ BitVec %d)) "
+ "(store (|%s#%d#%d| state) %s %s)) ; %s\n",
+ get_id(module), arrayid, i+1, get_id(module), abits, width,
+ get_id(module), arrayid, i, addr.c_str(), data.c_str(), get_id(cell)));
+ }
}
std::string expr_d = stringf("(|%s#%d#%d| state)", get_id(module), arrayid, wr_ports);
std::string expr_q = stringf("(|%s#%d#0| next_state)", get_id(module), arrayid);
trans.push_back(stringf(" (= %s %s) ; %s\n", expr_d.c_str(), expr_q.c_str(), get_id(cell)));
+ ex_state_eq.push_back(stringf("(= (|%s#%d#0| state) (|%s#%d#0| other_state))", get_id(module), arrayid, get_id(module), arrayid));
+
+ if (async_read)
+ hier.push_back(stringf(" (= %s (|%s| state)) ; %s\n", expr_d.c_str(), final_memstate.c_str(), get_id(cell)));
Const init_data = cell->getParam("\\INIT");
int memsize = cell->getParam("\\SIZE").as_int();
@@ -737,46 +1107,20 @@ struct Smt2Worker
if (bit == State::S0 || bit == State::S1)
gen_init_constr = true;
- if (gen_init_constr) {
- init_list.push_back(stringf("(= (select (|%s#%d#0| state) #b%s) #b%s) ; %s[%d]",
- get_id(module), arrayid, Const(i, abits).as_string().c_str(),
- initword.as_string().c_str(), get_id(cell), i));
+ if (gen_init_constr)
+ {
+ if (statebv)
+ /* FIXME */;
+ else
+ init_list.push_back(stringf("(= (select (|%s#%d#0| state) #b%s) #b%s) ; %s[%d]",
+ get_id(module), arrayid, Const(i, abits).as_string().c_str(),
+ initword.as_string().c_str(), get_id(cell), i));
}
}
}
}
}
- if (verbose) log("=> export logic driving hierarchical cells\n");
-
- while (!hiercells_queue.empty())
- {
- std::set<RTLIL::Cell*> queue;
- queue.swap(hiercells_queue);
-
- for (auto cell : queue)
- {
- string cell_state = stringf("(|%s_h %s| state)", get_id(module), get_id(cell->name));
- Module *m = module->design->module(cell->type);
- log_assert(m != nullptr);
-
- for (auto &conn : cell->connections())
- {
- Wire *w = m->wire(conn.first);
- SigSpec sig = sigmap(conn.second);
-
- if (bvmode || GetSize(w) == 1) {
- hier.push_back(stringf(" (= %s (|%s_n %s| %s)) ; %s.%s\n", (GetSize(w) > 1 ? get_bv(sig) : get_bool(sig)).c_str(),
- get_id(cell->type), get_id(w), cell_state.c_str(), get_id(cell->type), get_id(w)));
- } else {
- for (int i = 0; i < GetSize(w); i++)
- hier.push_back(stringf(" (= %s (|%s_n %s %d| %s)) ; %s.%s[%d]\n", get_bool(sig[i]).c_str(),
- get_id(cell->type), get_id(w), i, cell_state.c_str(), get_id(cell->type), get_id(w), i));
- }
- }
- }
- }
-
if (verbose) log("=> finalizing SMT2 representation of %s.\n", log_id(module));
for (auto c : hiercells) {
@@ -786,6 +1130,37 @@ struct Smt2Worker
hier.push_back(stringf(" (|%s_h| (|%s_h %s| state))\n", get_id(c->type), get_id(module), get_id(c->name)));
trans.push_back(stringf(" (|%s_t| (|%s_h %s| state) (|%s_h %s| next_state))\n",
get_id(c->type), get_id(module), get_id(c->name), get_id(module), get_id(c->name)));
+ ex_state_eq.push_back(stringf("(|%s_ex_state_eq| (|%s_h %s| state) (|%s_h %s| other_state))\n",
+ get_id(c->type), get_id(module), get_id(c->name), get_id(module), get_id(c->name)));
+ }
+
+ if (forallmode)
+ {
+ string expr = ex_state_eq.empty() ? "true" : "(and";
+ if (!ex_state_eq.empty()) {
+ if (GetSize(ex_state_eq) == 1) {
+ expr = "\n " + ex_state_eq.front() + "\n";
+ } else {
+ for (auto &str : ex_state_eq)
+ expr += stringf("\n %s", str.c_str());
+ expr += "\n)";
+ }
+ }
+ decls.push_back(stringf("(define-fun |%s_ex_state_eq| ((state |%s_s|) (other_state |%s_s|)) Bool %s)\n",
+ get_id(module), get_id(module), get_id(module), expr.c_str()));
+
+ expr = ex_input_eq.empty() ? "true" : "(and";
+ if (!ex_input_eq.empty()) {
+ if (GetSize(ex_input_eq) == 1) {
+ expr = "\n " + ex_input_eq.front() + "\n";
+ } else {
+ for (auto &str : ex_input_eq)
+ expr += stringf("\n %s", str.c_str());
+ expr += "\n)";
+ }
+ }
+ decls.push_back(stringf("(define-fun |%s_ex_input_eq| ((state |%s_s|) (other_state |%s_s|)) Bool %s)\n",
+ get_id(module), get_id(module), get_id(module), expr.c_str()));
}
string assert_expr = assert_list.empty() ? "true" : "(and";
@@ -832,6 +1207,18 @@ struct Smt2Worker
{
f << stringf("; yosys-smt2-module %s\n", get_id(module));
+ if (statebv) {
+ f << stringf("(define-sort |%s_s| () (_ BitVec %d))\n", get_id(module), statebv_width);
+ mod_stbv_width[module->name] = statebv_width;
+ } else
+ if (statedt) {
+ f << stringf("(declare-datatype |%s_s| ((|%s_mk|\n", get_id(module), get_id(module));
+ for (auto it : dtmembers)
+ f << it;
+ f << stringf(")))\n");
+ } else
+ f << stringf("(declare-sort |%s_s| 0)\n", get_id(module));
+
for (auto it : decls)
f << it;
@@ -864,44 +1251,92 @@ struct Smt2Worker
struct Smt2Backend : public Backend {
Smt2Backend() : Backend("smt2", "write design to SMT-LIBv2 file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" write_smt2 [options] [filename]\n");
log("\n");
log("Write a SMT-LIBv2 [1] description of the current design. For a module with name\n");
- log("'<mod>' this will declare the sort '<mod>_s' (state of the module) and the\n");
- log("functions operating on that state.\n");
+ log("'<mod>' this will declare the sort '<mod>_s' (state of the module) and will\n");
+ log("define and declare functions operating on that state.\n");
+ log("\n");
+ log("The following SMT2 functions are generated for a module with name '<mod>'.\n");
+ log("Some declarations/definitions are printed with a special comment. A prover\n");
+ log("using the SMT2 files can use those comments to collect all relevant metadata\n");
+ log("about the design.\n");
+ log("\n");
+ log(" ; yosys-smt2-module <mod>\n");
+ log(" (declare-sort |<mod>_s| 0)\n");
+ log(" The sort representing a state of module <mod>.\n");
+ log("\n");
+ log(" (define-fun |<mod>_h| ((state |<mod>_s|)) Bool (...))\n");
+ log(" This function must be asserted for each state to establish the\n");
+ log(" design hierarchy.\n");
+ log("\n");
+ log(" ; yosys-smt2-input <wirename> <width>\n");
+ log(" ; yosys-smt2-output <wirename> <width>\n");
+ log(" ; yosys-smt2-register <wirename> <width>\n");
+ log(" ; yosys-smt2-wire <wirename> <width>\n");
+ log(" (define-fun |<mod>_n <wirename>| (|<mod>_s|) (_ BitVec <width>))\n");
+ log(" (define-fun |<mod>_n <wirename>| (|<mod>_s|) Bool)\n");
+ log(" For each port, register, and wire with the 'keep' attribute set an\n");
+ log(" accessor function is generated. Single-bit wires are returned as Bool,\n");
+ log(" multi-bit wires as BitVec.\n");
+ log("\n");
+ log(" ; yosys-smt2-cell <submod> <instancename>\n");
+ log(" (declare-fun |<mod>_h <instancename>| (|<mod>_s|) |<submod>_s|)\n");
+ log(" There is a function like that for each hierarchical instance. It\n");
+ log(" returns the sort that represents the state of the sub-module that\n");
+ log(" implements the instance.\n");
+ log("\n");
+ log(" (declare-fun |<mod>_is| (|<mod>_s|) Bool)\n");
+ log(" This function must be asserted 'true' for initial states, and 'false'\n");
+ log(" otherwise.\n");
+ log("\n");
+ log(" (define-fun |<mod>_i| ((state |<mod>_s|)) Bool (...))\n");
+ log(" This function must be asserted 'true' for initial states. For\n");
+ log(" non-initial states it must be left unconstrained.\n");
log("\n");
- log("The '<mod>_s' sort represents a module state. Additional '<mod>_n' functions\n");
- log("are provided that can be used to access the values of the signals in the module.\n");
- log("By default only ports, registers, and wires with the 'keep' attribute set are\n");
- log("made available via such functions. With the -nobv option, multi-bit wires are\n");
- log("exported as separate functions of type Bool for the individual bits. Without\n");
- log("-nobv multi-bit wires are exported as single functions of type BitVec.\n");
+ log(" (define-fun |<mod>_t| ((state |<mod>_s|) (next_state |<mod>_s|)) Bool (...))\n");
+ log(" This function evaluates to 'true' if the states 'state' and\n");
+ log(" 'next_state' form a valid state transition.\n");
log("\n");
- log("The '<mod>_t' function evaluates to 'true' when the given pair of states\n");
- log("describes a valid state transition.\n");
+ log(" (define-fun |<mod>_a| ((state |<mod>_s|)) Bool (...))\n");
+ log(" This function evaluates to 'true' if all assertions hold in the state.\n");
log("\n");
- log("The '<mod>_a' function evaluates to 'true' when the given state satisfies\n");
- log("the asserts in the module.\n");
+ log(" (define-fun |<mod>_u| ((state |<mod>_s|)) Bool (...))\n");
+ log(" This function evaluates to 'true' if all assumptions hold in the state.\n");
log("\n");
- log("The '<mod>_u' function evaluates to 'true' when the given state satisfies\n");
- log("the assumptions in the module.\n");
+ log(" ; yosys-smt2-assert <id> <filename:linenum>\n");
+ log(" (define-fun |<mod>_a <id>| ((state |<mod>_s|)) Bool (...))\n");
+ log(" Each $assert cell is converted into one of this functions. The function\n");
+ log(" evaluates to 'true' if the assert statement holds in the state.\n");
log("\n");
- log("The '<mod>_i' function evaluates to 'true' when the given state conforms\n");
- log("to the initial state. Furthermore the '<mod>_is' function should be asserted\n");
- log("to be true for initial states in addition to '<mod>_i', and should be\n");
- log("asserted to be false for non-initial states.\n");
+ log(" ; yosys-smt2-assume <id> <filename:linenum>\n");
+ log(" (define-fun |<mod>_u <id>| ((state |<mod>_s|)) Bool (...))\n");
+ log(" Each $assume cell is converted into one of this functions. The function\n");
+ log(" evaluates to 'true' if the assume statement holds in the state.\n");
log("\n");
- log("For hierarchical designs, the '<mod>_h' function must be asserted for each\n");
- log("state to establish the design hierarchy. The '<mod>_h <cellname>' function\n");
- log("evaluates to the state corresponding to the given cell within <mod>.\n");
+ log(" ; yosys-smt2-cover <id> <filename:linenum>\n");
+ log(" (define-fun |<mod>_c <id>| ((state |<mod>_s|)) Bool (...))\n");
+ log(" Each $cover cell is converted into one of this functions. The function\n");
+ log(" evaluates to 'true' if the cover statement is activated in the state.\n");
+ log("\n");
+ log("Options:\n");
log("\n");
log(" -verbose\n");
log(" this will print the recursive walk used to export the modules.\n");
log("\n");
+ log(" -stbv\n");
+ log(" Use a BitVec sort to represent a state instead of an uninterpreted\n");
+ log(" sort. As a side-effect this will prevent use of arrays to model\n");
+ log(" memories.\n");
+ log("\n");
+ log(" -stdt\n");
+ log(" Use SMT-LIB 2.6 style datatypes to represent a state instead of an\n");
+ log(" uninterpreted sort.\n");
+ log("\n");
log(" -nobv\n");
log(" disable support for BitVec (FixedSizeBitVectors theory). without this\n");
log(" option multi-bit wires are represented using the BitVec sort and\n");
@@ -972,10 +1407,11 @@ struct Smt2Backend : public Backend {
log("from non-zero to zero in the test design.\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::ifstream template_f;
- bool bvmode = true, memmode = true, wiresmode = false, verbose = false;
+ bool bvmode = true, memmode = true, wiresmode = false, verbose = false, statebv = false, statedt = false;
+ bool forallmode = false;
log_header(design, "Executing SMT2 backend.\n");
@@ -992,6 +1428,16 @@ struct Smt2Backend : public Backend {
log_warning("Options -bv and -mem are now the default. Support for -bv and -mem will be removed in the future.\n");
continue;
}
+ if (args[argidx] == "-stbv") {
+ statebv = true;
+ statedt = false;
+ continue;
+ }
+ if (args[argidx] == "-stdt") {
+ statebv = false;
+ statedt = true;
+ continue;
+ }
if (args[argidx] == "-nobv") {
bvmode = false;
memmode = false;
@@ -1033,6 +1479,12 @@ struct Smt2Backend : public Backend {
if (!memmode)
*f << stringf("; yosys-smt2-nomem\n");
+ if (statebv)
+ *f << stringf("; yosys-smt2-stbv\n");
+
+ if (statedt)
+ *f << stringf("; yosys-smt2-stdt\n");
+
std::vector<RTLIL::Module*> sorted_modules;
// extract module dependencies
@@ -1062,17 +1514,31 @@ struct Smt2Backend : public Backend {
module_deps.erase(sorted_modules.at(sorted_modules_idx++));
}
+ dict<IdString, int> mod_stbv_width;
+ dict<IdString, dict<IdString, pair<bool, bool>>> mod_clk_cache;
Module *topmod = design->top_module();
std::string topmod_id;
for (auto module : sorted_modules)
+ for (auto cell : module->cells())
+ if (cell->type.in("$allconst", "$allseq"))
+ goto found_forall;
+ if (0) {
+ found_forall:
+ forallmode = true;
+ *f << stringf("; yosys-smt2-forall\n");
+ if (!statebv && !statedt)
+ log_error("Forall-exists problems are only supported in -stbv or -stdt mode.\n");
+ }
+
+ for (auto module : sorted_modules)
{
if (module->get_bool_attribute("\\blackbox") || module->has_memories_warn() || module->has_processes_warn())
continue;
log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module));
- Smt2Worker worker(module, bvmode, memmode, wiresmode, verbose);
+ Smt2Worker worker(module, bvmode, memmode, wiresmode, verbose, statebv, statedt, forallmode, mod_stbv_width, mod_clk_cache);
worker.run();
worker.write(*f);
diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py
index 04c25f91..6af2a5ac 100644
--- a/backends/smt2/smtbmc.py
+++ b/backends/smt2/smtbmc.py
@@ -22,21 +22,32 @@ import os, sys, getopt, re
from smtio import SmtIo, SmtOpts, MkVcd
from collections import defaultdict
+got_topt = False
skip_steps = 0
step_size = 1
num_steps = 20
+append_steps = 0
vcdfile = None
cexfile = None
+aimfile = None
+aiwfile = None
+aigheader = True
vlogtbfile = None
+vlogtbtop = None
inconstr = list()
outconstr = None
gentrace = False
+covermode = False
tempind = False
dumpall = False
assume_skipped = None
final_only = False
topmod = None
noinfo = False
+presat = False
+smtcinit = False
+smtctop = None
+noinit = False
so = SmtOpts()
@@ -56,6 +67,9 @@ yosys-smtbmc [options] <yosys_smt2_output>
-i
instead of BMC run temporal induction
+ -c
+ instead of regular BMC run cover analysis
+
-m <module_name>
name of the top module
@@ -65,10 +79,30 @@ yosys-smtbmc [options] <yosys_smt2_output>
--cex <cex_filename>
read cex file as written by ABC's "write_cex -n"
+ --aig <prefix>
+ read AIGER map file (as written by Yosys' "write_aiger -map")
+ and AIGER witness file. The file names are <prefix>.aim for
+ the map file and <prefix>.aiw for the witness file.
+
+ --aig <aim_filename>:<aiw_filename>
+ like above, but for map files and witness files that do not
+ share a filename prefix (or use differen file extensions).
+
+ --aig-noheader
+ the AIGER witness file does not include the status and
+ properties lines.
+
--noinfo
only run the core proof, do not collect and print any
additional information (e.g. which assert failed)
+ --presat
+ check if the design with assumptions but without assertions
+ is SAT before checking if assertions are UNSAT. This will
+ detect if there are contradicting assumtions. In some cases
+ this will also help to "warmup" the solver, potentially
+ yielding a speedup.
+
--final-only
only check final constraints, assume base case
@@ -85,25 +119,48 @@ yosys-smtbmc [options] <yosys_smt2_output>
--dump-vlogtb <verilog_filename>
write trace as Verilog test bench
+ --vlogtb-top <hierarchical_name>
+ use the given entity as top module for the generated
+ Verilog test bench. The <hierarchical_name> is relative
+ to the design top module without the top module name.
+
--dump-smtc <constr_filename>
write trace as constraints file
+ --smtc-init
+ write just the last state as initial constraint to smtc file
+
+ --smtc-top <old>[:<new>]
+ replace <old> with <new> in constraints dumped to smtc
+ file and only dump object below <old> in design hierarchy.
+
+ --noinit
+ do not assume initial conditions in state 0
+
--dump-all
when using -g or -i, create a dump file for each
step. The character '%' is replaces in all dump
filenames with the step number.
+
+ --append <num_steps>
+ add <num_steps> time steps at the end of the trace
+ when creating a counter example (this additional time
+ steps will still be constrained by assumtions)
""" + so.helpmsg())
sys.exit(1)
try:
- opts, args = getopt.getopt(sys.argv[1:], so.shortopts + "t:igm:", so.longopts +
- ["final-only", "assume-skipped=", "smtc=", "cex=", "dump-vcd=", "dump-vlogtb=", "dump-smtc=", "dump-all", "noinfo"])
+ opts, args = getopt.getopt(sys.argv[1:], so.shortopts + "t:igcm:", so.longopts +
+ ["final-only", "assume-skipped=", "smtc=", "cex=", "aig=", "aig-noheader", "presat",
+ "dump-vcd=", "dump-vlogtb=", "vlogtb-top=", "dump-smtc=", "dump-all", "noinfo", "append=",
+ "smtc-init", "smtc-top=", "noinit"])
except:
usage()
for o, a in opts:
if o == "-t":
+ got_topt = True
a = a.split(":")
if len(a) == 1:
num_steps = int(a[0])
@@ -115,7 +172,7 @@ for o, a in opts:
step_size = int(a[1])
num_steps = int(a[2])
else:
- assert 0
+ assert False
elif o == "--assume-skipped":
assume_skipped = int(a)
elif o == "--final-only":
@@ -124,20 +181,46 @@ for o, a in opts:
inconstr.append(a)
elif o == "--cex":
cexfile = a
+ elif o == "--aig":
+ if ":" in a:
+ aimfile, aiwfile = a.split(":")
+ else:
+ aimfile = a + ".aim"
+ aiwfile = a + ".aiw"
+ elif o == "--aig-noheader":
+ aigheader = False
elif o == "--dump-vcd":
vcdfile = a
elif o == "--dump-vlogtb":
vlogtbfile = a
+ elif o == "--vlogtb-top":
+ vlogtbtop = a
elif o == "--dump-smtc":
outconstr = a
+ elif o == "--smtc-init":
+ smtcinit = True
+ elif o == "--smtc-top":
+ smtctop = a.split(":")
+ if len(smtctop) == 1:
+ smtctop.append("")
+ assert len(smtctop) == 2
+ smtctop = tuple(smtctop)
elif o == "--dump-all":
dumpall = True
+ elif o == "--presat":
+ presat = True
elif o == "--noinfo":
noinfo = True
+ elif o == "--noinit":
+ noinit = True
+ elif o == "--append":
+ append_steps = int(a)
elif o == "-i":
tempind = True
elif o == "-g":
gentrace = True
+ elif o == "-c":
+ covermode = True
elif o == "-m":
topmod = a
elif so.handle(o, a):
@@ -148,6 +231,8 @@ for o, a in opts:
if len(args) != 1:
usage()
+if sum([tempind, gentrace, covermode]) > 1:
+ usage()
constr_final_start = None
constr_asserts = defaultdict(list)
@@ -182,12 +267,11 @@ for fn in inconstr:
current_states = set(["final-%d" % i for i in range(0, num_steps+1)])
constr_final_start = 0
elif len(tokens) == 2:
- i = int(tokens[1])
- assert i < 0
- current_states = set(["final-%d" % i for i in range(-i, num_steps+1)])
- constr_final_start = -i if constr_final_start is None else min(constr_final_start, -i)
+ arg = abs(int(tokens[1]))
+ current_states = set(["final-%d" % i for i in range(arg, num_steps+1)])
+ constr_final_start = arg if constr_final_start is None else min(constr_final_start, arg)
else:
- assert 0
+ assert False
continue
if tokens[0] == "state":
@@ -206,18 +290,17 @@ for fn in inconstr:
for i in range(lower, upper+1):
current_states.add(i)
else:
- assert 0
+ assert False
continue
if tokens[0] == "always":
if len(tokens) == 1:
current_states = set(range(0, num_steps+1))
elif len(tokens) == 2:
- i = int(tokens[1])
- assert i < 0
- current_states = set(range(-i, num_steps+1))
+ arg = abs(int(tokens[1]))
+ current_states = set(range(arg, num_steps+1))
else:
- assert 0
+ assert False
continue
if tokens[0] == "assert":
@@ -244,7 +327,7 @@ for fn in inconstr:
so.logic = " ".join(tokens[1:])
continue
- assert 0
+ assert False
def get_constr_expr(db, state, final=False, getvalues=False):
@@ -255,7 +338,7 @@ def get_constr_expr(db, state, final=False, getvalues=False):
if state not in db:
return ([], [], []) if getvalues else "true"
- netref_regex = re.compile(r'(^|[( ])\[(-?[0-9]+:|)([^\]]*)\](?=[ )]|$)')
+ netref_regex = re.compile(r'(^|[( ])\[(-?[0-9]+:|)([^\]]*|\S*)\](?=[ )]|$)')
def replace_netref(match):
state_sel = match.group(2)
@@ -318,6 +401,11 @@ assert topmod is not None
assert topmod in smt.modinfo
if cexfile is not None:
+ if not got_topt:
+ assume_skipped = 0
+ skip_steps = 0
+ num_steps = 0
+
with open(cexfile, "r") as f:
cex_regex = re.compile(r'([^\[@=]+)(\[\d+\])?([^@=]*)(@\d+)=([01])')
for entry in f.read().split():
@@ -349,6 +437,144 @@ if cexfile is not None:
# print("cex@%d: %s" % (step, smtexpr))
constr_assumes[step].append((cexfile, smtexpr))
+ if not got_topt:
+ skip_steps = max(skip_steps, step)
+ num_steps = max(num_steps, step+1)
+
+if aimfile is not None:
+ input_map = dict()
+ init_map = dict()
+ latch_map = dict()
+
+ if not got_topt:
+ assume_skipped = 0
+ skip_steps = 0
+ num_steps = 0
+
+ with open(aimfile, "r") as f:
+ for entry in f.read().splitlines():
+ entry = entry.split()
+
+ if entry[0] == "input":
+ input_map[int(entry[1])] = (entry[3], int(entry[2]))
+ continue
+
+ if entry[0] == "init":
+ init_map[int(entry[1])] = (entry[3], int(entry[2]))
+ continue
+
+ if entry[0] in ["latch", "invlatch"]:
+ latch_map[int(entry[1])] = (entry[3], int(entry[2]), entry[0] == "invlatch")
+ continue
+
+ if entry[0] in ["output", "wire"]:
+ continue
+
+ assert False
+
+ with open(aiwfile, "r") as f:
+ got_state = False
+ got_ffinit = False
+ step = 0
+
+ if not aigheader:
+ got_state = True
+
+ for entry in f.read().splitlines():
+ if len(entry) == 0 or entry[0] in "bcjfu.":
+ continue
+
+ if not got_state:
+ got_state = True
+ assert entry == "1"
+ continue
+
+ if not got_ffinit:
+ got_ffinit = True
+ if len(init_map) == 0:
+ for i in range(len(entry)):
+ if entry[i] == "x":
+ continue
+
+ if i in latch_map:
+ value = int(entry[i])
+ name = latch_map[i][0]
+ bitidx = latch_map[i][1]
+ invert = latch_map[i][2]
+
+ if invert:
+ value = 1 - value
+
+ path = smt.get_path(topmod, name)
+ width = smt.net_width(topmod, path)
+
+ if width == 1:
+ assert bitidx == 0
+ smtexpr = "(= [%s] %s)" % (name, "true" if value else "false")
+ else:
+ smtexpr = "(= ((_ extract %d %d) [%s]) #b%d)" % (bitidx, bitidx, name, value)
+
+ constr_assumes[0].append((cexfile, smtexpr))
+ continue
+
+ for i in range(len(entry)):
+ if entry[i] == "x":
+ continue
+
+ if (step == 0) and (i in init_map):
+ value = int(entry[i])
+ name = init_map[i][0]
+ bitidx = init_map[i][1]
+
+ path = smt.get_path(topmod, name)
+
+ if not smt.net_exists(topmod, path):
+ match = re.match(r"(.*)\[(\d+)\]$", path[-1])
+ if match:
+ path[-1] = match.group(1)
+ addr = int(match.group(2))
+
+ if not match or not smt.mem_exists(topmod, path):
+ print_msg("Ignoring init value for unknown net: %s" % (name))
+ continue
+
+ meminfo = smt.mem_info(topmod, path)
+ smtexpr = "(select [%s] #b%s)" % (".".join(path), bin(addr)[2:].zfill(meminfo[0]))
+ width = meminfo[1]
+
+ else:
+ smtexpr = "[%s]" % name
+ width = smt.net_width(topmod, path)
+
+ if width == 1:
+ assert bitidx == 0
+ smtexpr = "(= %s %s)" % (smtexpr, "true" if value else "false")
+ else:
+ smtexpr = "(= ((_ extract %d %d) %s) #b%d)" % (bitidx, bitidx, smtexpr, value)
+
+ constr_assumes[0].append((cexfile, smtexpr))
+
+ if i in input_map:
+ value = int(entry[i])
+ name = input_map[i][0]
+ bitidx = input_map[i][1]
+
+ path = smt.get_path(topmod, name)
+ width = smt.net_width(topmod, path)
+
+ if width == 1:
+ assert bitidx == 0
+ smtexpr = "(= [%s] %s)" % (name, "true" if value else "false")
+ else:
+ smtexpr = "(= ((_ extract %d %d) [%s]) #b%d)" % (bitidx, bitidx, name, value)
+
+ constr_assumes[step].append((cexfile, smtexpr))
+
+ if not got_topt:
+ skip_steps = max(skip_steps, step)
+ num_steps = max(num_steps, step+1)
+ step += 1
+
def write_vcd_trace(steps_start, steps_stop, index):
filename = vcdfile.replace("%", index)
print_msg("Writing trace to VCD file: %s" % (filename))
@@ -363,14 +589,123 @@ def write_vcd_trace(steps_start, steps_stop, index):
if n.startswith("$"):
hidden_net = True
if not hidden_net:
- vcd.add_net([topmod] + netpath, smt.net_width(topmod, netpath))
+ edge = smt.net_clock(topmod, netpath)
+ if edge is None:
+ vcd.add_net([topmod] + netpath, smt.net_width(topmod, netpath))
+ else:
+ vcd.add_clock([topmod] + netpath, edge)
path_list.append(netpath)
+ mem_trace_data = dict()
+ for mempath in sorted(smt.hiermems(topmod)):
+ abits, width, rports, wports, asyncwr = smt.mem_info(topmod, mempath)
+
+ expr_id = list()
+ expr_list = list()
+ for i in range(steps_start, steps_stop):
+ for j in range(rports):
+ expr_id.append(('R', i-steps_start, j, 'A'))
+ expr_id.append(('R', i-steps_start, j, 'D'))
+ expr_list.append(smt.mem_expr(topmod, "s%d" % i, mempath, "R%dA" % j))
+ expr_list.append(smt.mem_expr(topmod, "s%d" % i, mempath, "R%dD" % j))
+ for j in range(wports):
+ expr_id.append(('W', i-steps_start, j, 'A'))
+ expr_id.append(('W', i-steps_start, j, 'D'))
+ expr_id.append(('W', i-steps_start, j, 'M'))
+ expr_list.append(smt.mem_expr(topmod, "s%d" % i, mempath, "W%dA" % j))
+ expr_list.append(smt.mem_expr(topmod, "s%d" % i, mempath, "W%dD" % j))
+ expr_list.append(smt.mem_expr(topmod, "s%d" % i, mempath, "W%dM" % j))
+
+ rdata = list()
+ wdata = list()
+ addrs = set()
+
+ for eid, edat in zip(expr_id, smt.get_list(expr_list)):
+ t, i, j, f = eid
+
+ if t == 'R':
+ c = rdata
+ elif t == 'W':
+ c = wdata
+ else:
+ assert False
+
+ while len(c) <= i:
+ c.append(list())
+ c = c[i]
+
+ while len(c) <= j:
+ c.append(dict())
+ c = c[j]
+
+ c[f] = smt.bv2bin(edat)
+
+ if f == 'A':
+ addrs.add(c[f])
+
+ for addr in addrs:
+ tdata = list()
+ data = ["x"] * width
+ gotread = False
+
+ if len(wdata) == 0 and len(rdata) != 0:
+ wdata = [[]] * len(rdata)
+
+ assert len(rdata) == len(wdata)
+
+ for i in range(len(wdata)):
+ if not gotread:
+ for j_data in rdata[i]:
+ if j_data["A"] == addr:
+ data = list(j_data["D"])
+ gotread = True
+ break
+
+ if gotread:
+ buf = data[:]
+ for i in reversed(range(len(tdata))):
+ for k in range(width):
+ if tdata[i][k] == "x":
+ tdata[i][k] = buf[k]
+ else:
+ buf[k] = tdata[i][k]
+
+ if not asyncwr:
+ tdata.append(data[:])
+
+ for j_data in wdata[i]:
+ if j_data["A"] != addr:
+ continue
+
+ D = j_data["D"]
+ M = j_data["M"]
+
+ for k in range(width):
+ if M[k] == "1":
+ data[k] = D[k]
+
+ if asyncwr:
+ tdata.append(data[:])
+
+ assert len(tdata) == len(rdata)
+
+ netpath = mempath[:]
+ netpath[-1] += "<%0*x>" % ((len(addr)+3) // 4, int(addr, 2))
+ vcd.add_net([topmod] + netpath, width)
+
+ for i in range(steps_start, steps_stop):
+ if i not in mem_trace_data:
+ mem_trace_data[i] = list()
+ mem_trace_data[i].append((netpath, "".join(tdata[i-steps_start])))
+
for i in range(steps_start, steps_stop):
vcd.set_time(i)
value_list = smt.get_net_bin_list(topmod, path_list, "s%d" % i)
for path, value in zip(path_list, value_list):
vcd.set_net([topmod] + path, value)
+ if i in mem_trace_data:
+ for path, value in mem_trace_data[i]:
+ vcd.set_net([topmod] + path, value)
vcd.set_time(steps_stop)
@@ -379,18 +714,38 @@ def write_vlogtb_trace(steps_start, steps_stop, index):
filename = vlogtbfile.replace("%", index)
print_msg("Writing trace to Verilog testbench: %s" % (filename))
+ vlogtb_topmod = topmod
+ vlogtb_state = "s@@step_idx@@"
+
+ if vlogtbtop is not None:
+ for item in vlogtbtop.split("."):
+ if item in smt.modinfo[vlogtb_topmod].cells:
+ vlogtb_state = "(|%s_h %s| %s)" % (vlogtb_topmod, item, vlogtb_state)
+ vlogtb_topmod = smt.modinfo[vlogtb_topmod].cells[item]
+ else:
+ print_msg("Vlog top module '%s' not found: no cell '%s' in module '%s'" % (vlogtbtop, item, vlogtb_topmod))
+ break
+
with open(filename, "w") as f:
+ print("`ifndef VERILATOR", file=f)
print("module testbench;", file=f)
print(" reg [4095:0] vcdfile;", file=f)
- print(" reg clock = 0, genclock = 1;", file=f)
+ print(" reg clock;", file=f)
+ print("`else", file=f)
+ print("module testbench(input clock, output reg genclock);", file=f)
+ print(" initial genclock = 1;", file=f)
+ print("`endif", file=f)
+
+ print(" reg genclock = 1;", file=f)
+ print(" reg [31:0] cycle = 0;", file=f)
primary_inputs = list()
clock_inputs = set()
- for name in smt.modinfo[topmod].inputs:
+ for name in smt.modinfo[vlogtb_topmod].inputs:
if name in ["clk", "clock", "CLK", "CLOCK"]:
clock_inputs.add(name)
- width = smt.modinfo[topmod].wsize[name]
+ width = smt.modinfo[vlogtb_topmod].wsize[name]
primary_inputs.append((name, width))
for name, width in primary_inputs:
@@ -399,27 +754,32 @@ def write_vlogtb_trace(steps_start, steps_stop, index):
else:
print(" reg [%d:0] PI_%s;" % (width-1, name), file=f)
- print(" %s UUT (" % topmod, file=f)
+ print(" %s UUT (" % vlogtb_topmod, file=f)
print(",\n".join(" .{name}(PI_{name})".format(name=name) for name, _ in primary_inputs), file=f)
print(" );", file=f)
+ print("`ifndef VERILATOR", file=f)
print(" initial begin", file=f)
print(" if ($value$plusargs(\"vcd=%s\", vcdfile)) begin", file=f)
print(" $dumpfile(vcdfile);", file=f)
print(" $dumpvars(0, testbench);", file=f)
print(" end", file=f)
+ print(" #5 clock = 0;", file=f)
print(" while (genclock) begin", file=f)
- print(" #5; clock = 0;", file=f)
- print(" #5; clock = 1;", file=f)
+ print(" #5 clock = 0;", file=f)
+ print(" #5 clock = 1;", file=f)
print(" end", file=f)
print(" end", file=f)
+ print("`endif", file=f)
print(" initial begin", file=f)
- regs = sorted(smt.hiernets(topmod, regs_only=True))
- regvals = smt.get_net_bin_list(topmod, regs, "s%d" % steps_start)
+ regs = sorted(smt.hiernets(vlogtb_topmod, regs_only=True))
+ regvals = smt.get_net_bin_list(vlogtb_topmod, regs, vlogtb_state.replace("@@step_idx@@", str(steps_start)))
+ print("`ifndef VERILATOR", file=f)
print(" #1;", file=f)
+ print("`endif", file=f)
for reg, val in zip(regs, regvals):
hidden_net = False
for n in reg:
@@ -427,40 +787,74 @@ def write_vlogtb_trace(steps_start, steps_stop, index):
hidden_net = True
print(" %sUUT.%s = %d'b%s;" % ("// " if hidden_net else "", ".".join(reg), len(val), val), file=f)
- mems = sorted(smt.hiermems(topmod))
+ anyconsts = sorted(smt.hieranyconsts(vlogtb_topmod))
+ for info in anyconsts:
+ if info[3] is not None:
+ modstate = smt.net_expr(vlogtb_topmod, vlogtb_state.replace("@@step_idx@@", str(steps_start)), info[0])
+ value = smt.bv2bin(smt.get("(|%s| %s)" % (info[1], modstate)))
+ print(" UUT.%s = %d'b%s;" % (".".join(info[0] + [info[3]]), len(value), value), file=f);
+
+ mems = sorted(smt.hiermems(vlogtb_topmod))
for mempath in mems:
- abits, width, ports = smt.mem_info(topmod, "s%d" % steps_start, mempath)
- mem = smt.mem_expr(topmod, "s%d" % steps_start, mempath)
+ abits, width, rports, wports, asyncwr = smt.mem_info(vlogtb_topmod, mempath)
addr_expr_list = list()
+ data_expr_list = list()
for i in range(steps_start, steps_stop):
- for j in range(ports):
- addr_expr_list.append(smt.mem_expr(topmod, "s%d" % i, mempath, j))
+ for j in range(rports):
+ addr_expr_list.append(smt.mem_expr(vlogtb_topmod, vlogtb_state.replace("@@step_idx@@", str(i)), mempath, "R%dA" % j))
+ data_expr_list.append(smt.mem_expr(vlogtb_topmod, vlogtb_state.replace("@@step_idx@@", str(i)), mempath, "R%dD" % j))
- addr_list = set()
- for val in smt.get_list(addr_expr_list):
- addr_list.add(smt.bv2int(val))
+ addr_list = smt.get_list(addr_expr_list)
+ data_list = smt.get_list(data_expr_list)
- expr_list = list()
- for i in addr_list:
- expr_list.append("(select %s #b%s)" % (mem, format(i, "0%db" % abits)))
+ addr_data = dict()
+ for addr, data in zip(addr_list, data_list):
+ addr = smt.bv2bin(addr)
+ data = smt.bv2bin(data)
+ if addr not in addr_data:
+ addr_data[addr] = data
- for i, val in zip(addr_list, smt.get_list(expr_list)):
- val = smt.bv2bin(val)
- print(" UUT.%s[%d] = %d'b%s;" % (".".join(mempath), i, len(val), val), file=f)
+ for addr, data in addr_data.items():
+ print(" UUT.%s[%d'b%s] = %d'b%s;" % (".".join(mempath), len(addr), addr, len(data), data), file=f)
+
+ print("", file=f)
+ anyseqs = sorted(smt.hieranyseqs(vlogtb_topmod))
for i in range(steps_start, steps_stop):
pi_names = [[name] for name, _ in primary_inputs if name not in clock_inputs]
- pi_values = smt.get_net_bin_list(topmod, pi_names, "s%d" % i)
+ pi_values = smt.get_net_bin_list(vlogtb_topmod, pi_names, vlogtb_state.replace("@@step_idx@@", str(i)))
- print(" #1;", file=f)
print(" // state %d" % i, file=f)
+
if i > 0:
- print(" @(posedge clock);", file=f)
+ print(" if (cycle == %d) begin" % (i-1), file=f)
+
for name, val in zip(pi_names, pi_values):
- print(" PI_%s <= %d'b%s;" % (".".join(name), len(val), val), file=f)
+ if i > 0:
+ print(" PI_%s <= %d'b%s;" % (".".join(name), len(val), val), file=f)
+ else:
+ print(" PI_%s = %d'b%s;" % (".".join(name), len(val), val), file=f)
+
+ for info in anyseqs:
+ if info[3] is not None:
+ modstate = smt.net_expr(vlogtb_topmod, vlogtb_state.replace("@@step_idx@@", str(i)), info[0])
+ value = smt.bv2bin(smt.get("(|%s| %s)" % (info[1], modstate)))
+ if i > 0:
+ print(" UUT.%s <= %d'b%s;" % (".".join(info[0] + [info[3]]), len(value), value), file=f);
+ else:
+ print(" UUT.%s = %d'b%s;" % (".".join(info[0] + [info[3]]), len(value), value), file=f);
+
+ if i > 0:
+ print(" end", file=f)
+ print("", file=f)
+
+ if i == 0:
+ print(" end", file=f)
+ print(" always @(posedge clock) begin", file=f)
- print(" genclock = 0;", file=f)
+ print(" genclock <= cycle < %d;" % (steps_stop-1), file=f)
+ print(" cycle <= cycle + 1;", file=f)
print(" end", file=f)
print("endmodule", file=f)
@@ -470,52 +864,71 @@ def write_constr_trace(steps_start, steps_stop, index):
filename = outconstr.replace("%", index)
print_msg("Writing trace to constraints file: %s" % (filename))
+ constr_topmod = topmod
+ constr_state = "s@@step_idx@@"
+ constr_prefix = ""
+
+ if smtctop is not None:
+ for item in smtctop[0].split("."):
+ assert item in smt.modinfo[constr_topmod].cells
+ constr_state = "(|%s_h %s| %s)" % (constr_topmod, item, constr_state)
+ constr_topmod = smt.modinfo[constr_topmod].cells[item]
+ if smtctop[1] != "":
+ constr_prefix = smtctop[1] + "."
+
+ if smtcinit:
+ steps_start = steps_stop - 1
+
with open(filename, "w") as f:
primary_inputs = list()
- for name in smt.modinfo[topmod].inputs:
- width = smt.modinfo[topmod].wsize[name]
+ for name in smt.modinfo[constr_topmod].inputs:
+ width = smt.modinfo[constr_topmod].wsize[name]
primary_inputs.append((name, width))
- if steps_start == 0:
+ if steps_start == 0 or smtcinit:
print("initial", file=f)
else:
print("state %d" % steps_start, file=f)
- regnames = sorted(smt.hiernets(topmod, regs_only=True))
- regvals = smt.get_net_list(topmod, regnames, "s%d" % steps_start)
+ regnames = sorted(smt.hiernets(constr_topmod, regs_only=True))
+ regvals = smt.get_net_list(constr_topmod, regnames, constr_state.replace("@@step_idx@@", str(steps_start)))
for name, val in zip(regnames, regvals):
- print("assume (= [%s] %s)" % (".".join(name), val), file=f)
+ print("assume (= [%s%s] %s)" % (constr_prefix, ".".join(name), val), file=f)
- mems = sorted(smt.hiermems(topmod))
+ mems = sorted(smt.hiermems(constr_topmod))
for mempath in mems:
- abits, width, ports = smt.mem_info(topmod, "s%d" % steps_start, mempath)
- mem = smt.mem_expr(topmod, "s%d" % steps_start, mempath)
+ abits, width, rports, wports, asyncwr = smt.mem_info(constr_topmod, mempath)
addr_expr_list = list()
+ data_expr_list = list()
for i in range(steps_start, steps_stop):
- for j in range(ports):
- addr_expr_list.append(smt.mem_expr(topmod, "s%d" % i, mempath, j))
+ for j in range(rports):
+ addr_expr_list.append(smt.mem_expr(constr_topmod, constr_state.replace("@@step_idx@@", str(i)), mempath, "R%dA" % j))
+ data_expr_list.append(smt.mem_expr(constr_topmod, constr_state.replace("@@step_idx@@", str(i)), mempath, "R%dD" % j))
- addr_list = set((smt.bv2int(val) for val in smt.get_list(addr_expr_list)))
+ addr_list = smt.get_list(addr_expr_list)
+ data_list = smt.get_list(data_expr_list)
- expr_list = list()
- for i in addr_list:
- expr_list.append("(select %s #b%s)" % (mem, format(i, "0%db" % abits)))
+ addr_data = dict()
+ for addr, data in zip(addr_list, data_list):
+ if addr not in addr_data:
+ addr_data[addr] = data
- for i, val in zip(addr_list, smt.get_list(expr_list)):
- print("assume (= (select [%s] #b%s) %s)" % (".".join(mempath), format(i, "0%db" % abits), val), file=f)
+ for addr, data in addr_data.items():
+ print("assume (= (select [%s%s] %s) %s)" % (constr_prefix, ".".join(mempath), addr, data), file=f)
for k in range(steps_start, steps_stop):
- print("", file=f)
- print("state %d" % k, file=f)
+ if not smtcinit:
+ print("", file=f)
+ print("state %d" % k, file=f)
pi_names = [[name] for name, _ in sorted(primary_inputs)]
- pi_values = smt.get_net_list(topmod, pi_names, "s%d" % k)
+ pi_values = smt.get_net_list(constr_topmod, pi_names, constr_state.replace("@@step_idx@@", str(k)))
for name, val in zip(pi_names, pi_values):
- print("assume (= [%s] %s)" % (".".join(name), val), file=f)
+ print("assume (= [%s%s] %s)" % (constr_prefix, ".".join(name), val), file=f)
def write_trace(steps_start, steps_stop, index):
@@ -529,30 +942,40 @@ def write_trace(steps_start, steps_stop, index):
write_constr_trace(steps_start, steps_stop, index)
-def print_failed_asserts_worker(mod, state, path):
+def print_failed_asserts_worker(mod, state, path, extrainfo):
assert mod in smt.modinfo
+ found_failed_assert = False
if smt.get("(|%s_a| %s)" % (mod, state)) in ["true", "#b1"]:
return
for cellname, celltype in smt.modinfo[mod].cells.items():
- print_failed_asserts_worker(celltype, "(|%s_h %s| %s)" % (mod, cellname, state), path + "." + cellname)
+ if print_failed_asserts_worker(celltype, "(|%s_h %s| %s)" % (mod, cellname, state), path + "." + cellname, extrainfo):
+ found_failed_assert = True
for assertfun, assertinfo in smt.modinfo[mod].asserts.items():
if smt.get("(|%s| %s)" % (assertfun, state)) in ["false", "#b0"]:
- print_msg("Assert failed in %s: %s" % (path, assertinfo))
+ print_msg("Assert failed in %s: %s%s" % (path, assertinfo, extrainfo))
+ found_failed_assert = True
+
+ return found_failed_assert
-def print_failed_asserts(state, final=False):
+def print_failed_asserts(state, final=False, extrainfo=""):
if noinfo: return
loc_list, expr_list, value_list = get_constr_expr(constr_asserts, state, final=final, getvalues=True)
+ found_failed_assert = False
for loc, expr, value in zip(loc_list, expr_list, value_list):
if smt.bv2int(value) == 0:
- print_msg("Assert %s failed: %s" % (loc, expr))
+ print_msg("Assert %s failed: %s%s" % (loc, expr, extrainfo))
+ found_failed_assert = True
if not final:
- print_failed_asserts_worker(topmod, "s%d" % state, topmod)
+ if print_failed_asserts_worker(topmod, "s%d" % state, topmod, extrainfo):
+ found_failed_assert = True
+
+ return found_failed_assert
def print_anyconsts_worker(mod, state, path):
@@ -562,7 +985,10 @@ def print_anyconsts_worker(mod, state, path):
print_anyconsts_worker(celltype, "(|%s_h %s| %s)" % (mod, cellname, state), path + "." + cellname)
for fun, info in smt.modinfo[mod].anyconsts.items():
- print_msg("Value for anyconst in %s (%s): %d" % (path, info, smt.bv2int(smt.get("(|%s| %s)" % (fun, state)))))
+ if info[1] is None:
+ print_msg("Value for anyconst in %s (%s): %d" % (path, info[0], smt.bv2int(smt.get("(|%s| %s)" % (fun, state)))))
+ else:
+ print_msg("Value for anyconst %s.%s (%s): %d" % (path, info[1], info[0], smt.bv2int(smt.get("(|%s| %s)" % (fun, state)))))
def print_anyconsts(state):
@@ -570,23 +996,183 @@ def print_anyconsts(state):
print_anyconsts_worker(topmod, "s%d" % state, topmod)
+def get_cover_list(mod, base):
+ assert mod in smt.modinfo
+
+ cover_expr = list()
+ cover_desc = list()
+
+ for expr, desc in smt.modinfo[mod].covers.items():
+ cover_expr.append("(ite (|%s| %s) #b1 #b0)" % (expr, base))
+ cover_desc.append(desc)
+
+ for cell, submod in smt.modinfo[mod].cells.items():
+ e, d = get_cover_list(submod, "(|%s_h %s| %s)" % (mod, cell, base))
+ cover_expr += e
+ cover_desc += d
+
+ return cover_expr, cover_desc
+
+states = list()
+asserts_antecedent_cache = [list()]
+asserts_consequent_cache = [list()]
+asserts_cache_dirty = False
+
+def smt_state(step):
+ smt.write("(declare-fun s%d () |%s_s|)" % (step, topmod))
+ states.append("s%d" % step)
+
+def smt_assert(expr):
+ if expr == "true":
+ return
+
+ smt.write("(assert %s)" % expr)
+
+def smt_assert_antecedent(expr):
+ if expr == "true":
+ return
+
+ smt.write("(assert %s)" % expr)
+
+ global asserts_cache_dirty
+ asserts_cache_dirty = True
+ asserts_antecedent_cache[-1].append(expr)
+
+def smt_assert_consequent(expr):
+ if expr == "true":
+ return
+
+ smt.write("(assert %s)" % expr)
+
+ global asserts_cache_dirty
+ asserts_cache_dirty = True
+ asserts_consequent_cache[-1].append(expr)
+
+def smt_forall_assert():
+ if not smt.forall:
+ return
+
+ global asserts_cache_dirty
+ asserts_cache_dirty = False
+
+ def make_assert_expr(asserts_cache):
+ expr = list()
+ for lst in asserts_cache:
+ expr += lst
+
+ assert len(expr) != 0
+
+ if len(expr) == 1:
+ expr = expr[0]
+ else:
+ expr = "(and %s)" % (" ".join(expr))
+ return expr
+
+ antecedent_expr = make_assert_expr(asserts_antecedent_cache)
+ consequent_expr = make_assert_expr(asserts_consequent_cache)
+
+ states_db = set(states)
+ used_states_db = set()
+ new_antecedent_expr = list()
+ new_consequent_expr = list()
+ assert_expr = list()
+
+ def make_new_expr(new_expr, expr):
+ cursor = 0
+ while cursor < len(expr):
+ l = 1
+ if expr[cursor] in '|"':
+ while cursor+l+1 < len(expr) and expr[cursor] != expr[cursor+l]:
+ l += 1
+ l += 1
+ elif expr[cursor] not in '() ':
+ while cursor+l < len(expr) and expr[cursor+l] not in '|"() ':
+ l += 1
+
+ word = expr[cursor:cursor+l]
+ if word in states_db:
+ used_states_db.add(word)
+ word += "_"
+
+ new_expr.append(word)
+ cursor += l
+
+ make_new_expr(new_antecedent_expr, antecedent_expr)
+ make_new_expr(new_consequent_expr, consequent_expr)
+
+ new_antecedent_expr = ["".join(new_antecedent_expr)]
+ new_consequent_expr = ["".join(new_consequent_expr)]
+
+ if states[0] in used_states_db:
+ new_antecedent_expr.append("(|%s_ex_state_eq| %s %s_)" % (topmod, states[0], states[0]))
+ for s in states:
+ if s in used_states_db:
+ new_antecedent_expr.append("(|%s_ex_input_eq| %s %s_)" % (topmod, s, s))
+
+ if len(new_antecedent_expr) == 0:
+ new_antecedent_expr = "true"
+ elif len(new_antecedent_expr) == 1:
+ new_antecedent_expr = new_antecedent_expr[0]
+ else:
+ new_antecedent_expr = "(and %s)" % (" ".join(new_antecedent_expr))
+
+ if len(new_consequent_expr) == 0:
+ new_consequent_expr = "true"
+ elif len(new_consequent_expr) == 1:
+ new_consequent_expr = new_consequent_expr[0]
+ else:
+ new_consequent_expr = "(and %s)" % (" ".join(new_consequent_expr))
+
+ assert_expr.append("(assert (forall (")
+ first_state = True
+ for s in states:
+ if s in used_states_db:
+ assert_expr.append("%s(%s_ |%s_s|)" % ("" if first_state else " ", s, topmod))
+ first_state = False
+ assert_expr.append(") (=> %s %s)))" % (new_antecedent_expr, new_consequent_expr))
+
+ smt.write("".join(assert_expr))
+
+def smt_push():
+ global asserts_cache_dirty
+ asserts_cache_dirty = True
+ asserts_antecedent_cache.append(list())
+ asserts_consequent_cache.append(list())
+ smt.write("(push 1)")
+
+def smt_pop():
+ global asserts_cache_dirty
+ asserts_cache_dirty = True
+ asserts_antecedent_cache.pop()
+ asserts_consequent_cache.pop()
+ smt.write("(pop 1)")
+
+def smt_check_sat():
+ if asserts_cache_dirty:
+ smt_forall_assert()
+ return smt.check_sat()
+
if tempind:
retstatus = False
skip_counter = step_size
for step in range(num_steps, -1, -1):
- smt.write("(declare-fun s%d () |%s_s|)" % (step, topmod))
- smt.write("(assert (|%s_u| s%d))" % (topmod, step))
- smt.write("(assert (|%s_h| s%d))" % (topmod, step))
- smt.write("(assert (not (|%s_is| s%d)))" % (topmod, step))
- smt.write("(assert %s)" % get_constr_expr(constr_assumes, step))
+ if smt.forall:
+ print_msg("Temporal induction not supported for exists-forall problems.")
+ break
+
+ smt_state(step)
+ smt_assert_consequent("(|%s_u| s%d)" % (topmod, step))
+ smt_assert_antecedent("(|%s_h| s%d)" % (topmod, step))
+ smt_assert_antecedent("(not (|%s_is| s%d))" % (topmod, step))
+ smt_assert_consequent(get_constr_expr(constr_assumes, step))
if step == num_steps:
- smt.write("(assert (not (and (|%s_a| s%d) %s)))" % (topmod, step, get_constr_expr(constr_asserts, step)))
+ smt_assert("(not (and (|%s_a| s%d) %s))" % (topmod, step, get_constr_expr(constr_asserts, step)))
else:
- smt.write("(assert (|%s_t| s%d s%d))" % (topmod, step, step+1))
- smt.write("(assert (|%s_a| s%d))" % (topmod, step))
- smt.write("(assert %s)" % get_constr_expr(constr_asserts, step))
+ smt_assert_antecedent("(|%s_t| s%d s%d)" % (topmod, step, step+1))
+ smt_assert("(|%s_a| s%d)" % (topmod, step))
+ smt_assert(get_constr_expr(constr_asserts, step))
if step > num_steps-skip_steps:
print_msg("Skipping induction in step %d.." % (step))
@@ -600,9 +1186,9 @@ if tempind:
skip_counter = 0
print_msg("Trying induction in step %d.." % (step))
- if smt.check_sat() == "sat":
+ if smt_check_sat() == "sat":
if step == 0:
- print("%s Temporal induction failed!" % smt.timestamp())
+ print_msg("Temporal induction failed!")
print_anyconsts(num_steps)
print_failed_asserts(num_steps)
write_trace(step, num_steps+1, '%')
@@ -613,33 +1199,135 @@ if tempind:
write_trace(step, num_steps+1, "%d" % step)
else:
- print("%s Temporal induction successful." % smt.timestamp())
+ print_msg("Temporal induction successful.")
retstatus = True
break
+elif covermode:
+ cover_expr, cover_desc = get_cover_list(topmod, "state")
+ cover_mask = "1" * len(cover_desc)
+
+ if len(cover_expr) > 1:
+ cover_expr = "(concat %s)" % " ".join(cover_expr)
+ elif len(cover_expr) == 1:
+ cover_expr = cover_expr[0]
+ else:
+ cover_expr = "#b0"
+
+ coveridx = 0
+ smt.write("(define-fun covers_0 ((state |%s_s|)) (_ BitVec %d) %s)" % (topmod, len(cover_desc), cover_expr))
-else: # not tempind
+ step = 0
+ retstatus = False
+ found_failed_assert = False
+
+ assert step_size == 1
+
+ while step < num_steps:
+ smt_state(step)
+ smt_assert_consequent("(|%s_u| s%d)" % (topmod, step))
+ smt_assert_antecedent("(|%s_h| s%d)" % (topmod, step))
+ smt_assert_consequent(get_constr_expr(constr_assumes, step))
+
+ if step == 0:
+ if noinit:
+ smt_assert_antecedent("(not (|%s_is| s%d))" % (topmod, step))
+ else:
+ smt_assert_antecedent("(|%s_i| s0)" % (topmod))
+ smt_assert_antecedent("(|%s_is| s0)" % (topmod))
+
+ else:
+ smt_assert_antecedent("(|%s_t| s%d s%d)" % (topmod, step-1, step))
+ smt_assert_antecedent("(not (|%s_is| s%d))" % (topmod, step))
+
+ while "1" in cover_mask:
+ print_msg("Checking cover reachability in step %d.." % (step))
+ smt_push()
+ smt_assert("(distinct (covers_%d s%d) #b%s)" % (coveridx, step, "0" * len(cover_desc)))
+
+ if smt_check_sat() == "unsat":
+ smt_pop()
+ break
+
+ if append_steps > 0:
+ for i in range(step+1, step+1+append_steps):
+ print_msg("Appending additional step %d." % i)
+ smt_state(i)
+ smt_assert_antecedent("(not (|%s_is| s%d))" % (topmod, i))
+ smt_assert_consequent("(|%s_u| s%d)" % (topmod, i))
+ smt_assert_antecedent("(|%s_h| s%d)" % (topmod, i))
+ smt_assert_antecedent("(|%s_t| s%d s%d)" % (topmod, i-1, i))
+ smt_assert_consequent(get_constr_expr(constr_assumes, i))
+ print_msg("Re-solving with appended steps..")
+ assert smt_check_sat() == "sat"
+
+ reached_covers = smt.bv2bin(smt.get("(covers_%d s%d)" % (coveridx, step)))
+ assert len(reached_covers) == len(cover_desc)
+
+ new_cover_mask = []
+
+ for i in range(len(reached_covers)):
+ if reached_covers[i] == "0":
+ new_cover_mask.append(cover_mask[i])
+ continue
+
+ print_msg("Reached cover statement at %s in step %d." % (cover_desc[i], step))
+ new_cover_mask.append("0")
+
+ cover_mask = "".join(new_cover_mask)
+
+ for i in range(step+1+append_steps):
+ if print_failed_asserts(i, extrainfo=" (step %d)" % i):
+ found_failed_assert = True
+
+ write_trace(0, step+1+append_steps, "%d" % coveridx)
+
+ if found_failed_assert:
+ break
+
+ coveridx += 1
+ smt_pop()
+ smt.write("(define-fun covers_%d ((state |%s_s|)) (_ BitVec %d) (bvand (covers_%d state) #b%s))" % (coveridx, topmod, len(cover_desc), coveridx-1, cover_mask))
+
+ if found_failed_assert:
+ break
+
+ if "1" not in cover_mask:
+ retstatus = True
+ break
+
+ step += 1
+
+ if "1" in cover_mask:
+ for i in range(len(cover_mask)):
+ if cover_mask[i] == "1":
+ print_msg("Unreached cover statement at %s." % cover_desc[i])
+
+else: # not tempind, covermode
step = 0
retstatus = True
while step < num_steps:
- smt.write("(declare-fun s%d () |%s_s|)" % (step, topmod))
- smt.write("(assert (|%s_u| s%d))" % (topmod, step))
- smt.write("(assert (|%s_h| s%d))" % (topmod, step))
- smt.write("(assert %s)" % get_constr_expr(constr_assumes, step))
+ smt_state(step)
+ smt_assert_consequent("(|%s_u| s%d)" % (topmod, step))
+ smt_assert_antecedent("(|%s_h| s%d)" % (topmod, step))
+ smt_assert_consequent(get_constr_expr(constr_assumes, step))
if step == 0:
- smt.write("(assert (|%s_i| s0))" % (topmod))
- smt.write("(assert (|%s_is| s0))" % (topmod))
+ if noinit:
+ smt_assert_antecedent("(not (|%s_is| s%d))" % (topmod, step))
+ else:
+ smt_assert_antecedent("(|%s_i| s0)" % (topmod))
+ smt_assert_antecedent("(|%s_is| s0)" % (topmod))
else:
- smt.write("(assert (|%s_t| s%d s%d))" % (topmod, step-1, step))
- smt.write("(assert (not (|%s_is| s%d)))" % (topmod, step))
+ smt_assert_antecedent("(|%s_t| s%d s%d)" % (topmod, step-1, step))
+ smt_assert_antecedent("(not (|%s_is| s%d))" % (topmod, step))
if step < skip_steps:
if assume_skipped is not None and step >= assume_skipped:
print_msg("Skipping step %d (and assuming pass).." % (step))
- smt.write("(assert (|%s_a| s%d))" % (topmod, step))
- smt.write("(assert %s)" % get_constr_expr(constr_asserts, step))
+ smt_assert("(|%s_a| s%d)" % (topmod, step))
+ smt_assert(get_constr_expr(constr_asserts, step))
else:
print_msg("Skipping step %d.." % (step))
step += 1
@@ -648,39 +1336,61 @@ else: # not tempind
last_check_step = step
for i in range(1, step_size):
if step+i < num_steps:
- smt.write("(declare-fun s%d () |%s_s|)" % (step+i, topmod))
- smt.write("(assert (|%s_u| s%d))" % (topmod, step+i))
- smt.write("(assert (|%s_h| s%d))" % (topmod, step+i))
- smt.write("(assert (|%s_t| s%d s%d))" % (topmod, step+i-1, step+i))
- smt.write("(assert %s)" % get_constr_expr(constr_assumes, step+i))
+ smt_state(step+i)
+ smt_assert_antecedent("(not (|%s_is| s%d))" % (topmod, step+i))
+ smt_assert_consequent("(|%s_u| s%d)" % (topmod, step+i))
+ smt_assert_antecedent("(|%s_h| s%d)" % (topmod, step+i))
+ smt_assert_antecedent("(|%s_t| s%d s%d)" % (topmod, step+i-1, step+i))
+ smt_assert_consequent(get_constr_expr(constr_assumes, step+i))
last_check_step = step+i
if not gentrace:
+ if presat:
+ if last_check_step == step:
+ print_msg("Checking assumptions in step %d.." % (step))
+ else:
+ print_msg("Checking assumptions in steps %d to %d.." % (step, last_check_step))
+
+ if smt_check_sat() == "unsat":
+ print("%s Warmup failed!" % smt.timestamp())
+ retstatus = False
+ break
+
if not final_only:
if last_check_step == step:
- print_msg("Checking asserts in step %d.." % (step))
+ print_msg("Checking assertions in step %d.." % (step))
else:
- print_msg("Checking asserts in steps %d to %d.." % (step, last_check_step))
- smt.write("(push 1)")
+ print_msg("Checking assertions in steps %d to %d.." % (step, last_check_step))
+ smt_push()
- smt.write("(assert (not (and %s)))" % " ".join(["(|%s_a| s%d)" % (topmod, i) for i in range(step, last_check_step+1)] +
+ smt_assert("(not (and %s))" % " ".join(["(|%s_a| s%d)" % (topmod, i) for i in range(step, last_check_step+1)] +
[get_constr_expr(constr_asserts, i) for i in range(step, last_check_step+1)]))
- if smt.check_sat() == "sat":
+ if smt_check_sat() == "sat":
print("%s BMC failed!" % smt.timestamp())
+ if append_steps > 0:
+ for i in range(last_check_step+1, last_check_step+1+append_steps):
+ print_msg("Appending additional step %d." % i)
+ smt_state(i)
+ smt_assert_antecedent("(not (|%s_is| s%d))" % (topmod, i))
+ smt_assert_consequent("(|%s_u| s%d)" % (topmod, i))
+ smt_assert_antecedent("(|%s_h| s%d)" % (topmod, i))
+ smt_assert_antecedent("(|%s_t| s%d s%d)" % (topmod, i-1, i))
+ smt_assert_consequent(get_constr_expr(constr_assumes, i))
+ assert smt_check_sat() == "sat"
print_anyconsts(step)
for i in range(step, last_check_step+1):
print_failed_asserts(i)
- write_trace(0, last_check_step+1, '%')
+ write_trace(0, last_check_step+1+append_steps, '%')
retstatus = False
break
- smt.write("(pop 1)")
+ smt_pop()
if (constr_final_start is not None) or (last_check_step+1 != num_steps):
for i in range(step, last_check_step+1):
- smt.write("(assert (|%s_a| s%d))" % (topmod, i))
- smt.write("(assert %s)" % get_constr_expr(constr_asserts, i))
+ smt_assert("(|%s_a| s%d)" % (topmod, i))
+ smt_assert(get_constr_expr(constr_asserts, i))
if constr_final_start is not None:
for i in range(step, last_check_step+1):
@@ -688,12 +1398,12 @@ else: # not tempind
continue
print_msg("Checking final constraints in step %d.." % (i))
- smt.write("(push 1)")
+ smt_push()
- smt.write("(assert %s)" % get_constr_expr(constr_assumes, i, final=True))
- smt.write("(assert (not %s))" % get_constr_expr(constr_asserts, i, final=True))
+ smt_assert_consequent(get_constr_expr(constr_assumes, i, final=True))
+ smt_assert("(not %s)" % get_constr_expr(constr_asserts, i, final=True))
- if smt.check_sat() == "sat":
+ if smt_check_sat() == "sat":
print("%s BMC failed!" % smt.timestamp())
print_anyconsts(i)
print_failed_asserts(i, final=True)
@@ -701,17 +1411,17 @@ else: # not tempind
retstatus = False
break
- smt.write("(pop 1)")
+ smt_pop()
if not retstatus:
break
else: # gentrace
for i in range(step, last_check_step+1):
- smt.write("(assert (|%s_a| s%d))" % (topmod, i))
- smt.write("(assert %s)" % get_constr_expr(constr_asserts, i))
+ smt_assert("(|%s_a| s%d)" % (topmod, i))
+ smt_assert(get_constr_expr(constr_asserts, i))
print_msg("Solving for step %d.." % (last_check_step))
- if smt.check_sat() != "sat":
+ if smt_check_sat() != "sat":
print("%s No solution found!" % smt.timestamp())
retstatus = False
break
@@ -722,7 +1432,7 @@ else: # not tempind
step += step_size
- if gentrace:
+ if gentrace and retstatus:
print_anyconsts(0)
write_trace(0, num_steps, '%')
diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py
index 865eed1f..3fc823e3 100644
--- a/backends/smt2/smtio.py
+++ b/backends/smt2/smtio.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python3
#
# yosys -- Yosys Open SYnthesis Suite
#
@@ -17,10 +16,55 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
-import sys, subprocess, re
+import sys, re, os, signal
+import subprocess
+if os.name == "posix":
+ import resource
from copy import deepcopy
from select import select
from time import time
+from queue import Queue, Empty
+from threading import Thread
+
+
+# This is needed so that the recursive SMT2 S-expression parser
+# does not run out of stack frames when parsing large expressions
+if os.name == "posix":
+ smtio_reclimit = 64 * 1024
+ smtio_stacksize = 128 * 1024 * 1024
+ if sys.getrecursionlimit() < smtio_reclimit:
+ sys.setrecursionlimit(smtio_reclimit)
+ if resource.getrlimit(resource.RLIMIT_STACK)[0] < smtio_stacksize:
+ resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, -1))
+
+
+# currently running solvers (so we can kill them)
+running_solvers = dict()
+forced_shutdown = False
+solvers_index = 0
+
+def force_shutdown(signum, frame):
+ global forced_shutdown
+ if not forced_shutdown:
+ forced_shutdown = True
+ if signum is not None:
+ print("<%s>" % signal.Signals(signum).name)
+ for p in running_solvers.values():
+ # os.killpg(os.getpgid(p.pid), signal.SIGTERM)
+ os.kill(p.pid, signal.SIGTERM)
+ sys.exit(1)
+
+if os.name == "posix":
+ signal.signal(signal.SIGHUP, force_shutdown)
+signal.signal(signal.SIGINT, force_shutdown)
+signal.signal(signal.SIGTERM, force_shutdown)
+
+def except_hook(exctype, value, traceback):
+ if not forced_shutdown:
+ sys.__excepthook__(exctype, value, traceback)
+ force_shutdown(None, None)
+
+sys.excepthook = except_hook
hex_dict = {
@@ -41,25 +85,38 @@ class SmtModInfo:
self.memories = dict()
self.wires = set()
self.wsize = dict()
+ self.clocks = dict()
self.cells = dict()
self.asserts = dict()
+ self.covers = dict()
self.anyconsts = dict()
+ self.anyseqs = dict()
+ self.allconsts = dict()
+ self.allseqs = dict()
+ self.asize = dict()
class SmtIo:
def __init__(self, opts=None):
+ global solvers_index
+
self.logic = None
self.logic_qf = True
self.logic_ax = True
self.logic_uf = True
self.logic_bv = True
+ self.logic_dt = False
+ self.forall = False
self.produce_models = True
self.smt2cache = [list()]
self.p = None
+ self.p_index = solvers_index
+ solvers_index += 1
if opts is not None:
self.logic = opts.logic
self.solver = opts.solver
+ self.solver_opts = opts.solver_opts
self.debug_print = opts.debug_print
self.debug_file = opts.debug_file
self.dummy_file = opts.dummy_file
@@ -70,34 +127,57 @@ class SmtIo:
self.nocomments = opts.nocomments
else:
- self.solver = "z3"
+ self.solver = "yices"
+ self.solver_opts = list()
self.debug_print = False
self.debug_file = None
self.dummy_file = None
- self.timeinfo = True
+ self.timeinfo = os.name != "nt"
self.unroll = False
self.noincr = False
self.info_stmts = list()
self.nocomments = False
+ self.start_time = time()
+
+ self.modinfo = dict()
+ self.curmod = None
+ self.topmod = None
+ self.setup_done = False
+
+ def __del__(self):
+ if self.p is not None and not forced_shutdown:
+ os.killpg(os.getpgid(self.p.pid), signal.SIGTERM)
+ if running_solvers is not None:
+ del running_solvers[self.p_index]
+
+ def setup(self):
+ assert not self.setup_done
+
+ if self.forall:
+ self.unroll = False
+
if self.solver == "yices":
- self.popen_vargs = ['yices-smt2', '--incremental']
+ self.popen_vargs = ['yices-smt2', '--incremental'] + self.solver_opts
if self.solver == "z3":
- self.popen_vargs = ['z3', '-smt2', '-in']
+ self.popen_vargs = ['z3', '-smt2', '-in'] + self.solver_opts
if self.solver == "cvc4":
- self.popen_vargs = ['cvc4', '--incremental', '--lang', 'smt2']
+ self.popen_vargs = ['cvc4', '--incremental', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts
if self.solver == "mathsat":
- self.popen_vargs = ['mathsat']
+ self.popen_vargs = ['mathsat'] + self.solver_opts
if self.solver == "boolector":
- self.popen_vargs = ['boolector', '--smt2', '-i']
+ self.popen_vargs = ['boolector', '--smt2', '-i'] + self.solver_opts
self.unroll = True
if self.solver == "abc":
- self.popen_vargs = ['yosys-abc', '-S', '%blast; &sweep -C 5000; &syn4; &cec -s -m -C 2000']
+ if len(self.solver_opts) > 0:
+ self.popen_vargs = ['yosys-abc', '-S', '; '.join(self.solver_opts)]
+ else:
+ self.popen_vargs = ['yosys-abc', '-S', '%blast; &sweep -C 5000; &syn4; &cec -s -m -C 2000']
self.logic_ax = False
self.unroll = True
self.noincr = True
@@ -109,9 +189,10 @@ class SmtIo:
if self.dummy_file is not None:
self.dummy_fd = open(self.dummy_file, "w")
if not self.noincr:
- self.p = subprocess.Popen(self.popen_vargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ self.p_open()
if self.unroll:
+ assert not self.forall
self.logic_uf = False
self.unroll_idcnt = 0
self.unroll_buffer = ""
@@ -121,36 +202,27 @@ class SmtIo:
self.unroll_cache = dict()
self.unroll_stack = list()
- self.start_time = time()
-
- self.modinfo = dict()
- self.curmod = None
- self.topmod = None
- self.setup_done = False
-
- def setup(self):
- assert not self.setup_done
-
if self.logic is None:
self.logic = ""
if self.logic_qf: self.logic += "QF_"
if self.logic_ax: self.logic += "A"
if self.logic_uf: self.logic += "UF"
if self.logic_bv: self.logic += "BV"
+ if self.logic_dt: self.logic = "ALL"
self.setup_done = True
+ for stmt in self.info_stmts:
+ self.write(stmt)
+
if self.produce_models:
self.write("(set-option :produce-models true)")
self.write("(set-logic %s)" % self.logic)
- for stmt in self.info_stmts:
- self.write(stmt)
-
def timestamp(self):
secs = int(time() - self.start_time)
- return "## %6d %3d:%02d:%02d " % (secs, secs // (60*60), (secs // 60) % 60, secs % 60)
+ return "## %3d:%02d:%02d " % (secs // (60*60), (secs // 60) % 60, secs % 60)
def replace_in_stmt(self, stmt, pat, repl):
if stmt == pat:
@@ -201,18 +273,75 @@ class SmtIo:
return stmt
+ def p_thread_main(self):
+ while True:
+ data = self.p.stdout.readline().decode("ascii")
+ if data == "": break
+ self.p_queue.put(data)
+ self.p_queue.put("")
+ self.p_running = False
+
+ def p_open(self):
+ assert self.p is None
+ self.p = subprocess.Popen(self.popen_vargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ running_solvers[self.p_index] = self.p
+ self.p_running = True
+ self.p_next = None
+ self.p_queue = Queue()
+ self.p_thread = Thread(target=self.p_thread_main)
+ self.p_thread.start()
+
+ def p_write(self, data, flush):
+ assert self.p is not None
+ self.p.stdin.write(bytes(data, "ascii"))
+ if flush: self.p.stdin.flush()
+
+ def p_read(self):
+ assert self.p is not None
+ if self.p_next is not None:
+ data = self.p_next
+ self.p_next = None
+ return data
+ if not self.p_running:
+ return ""
+ return self.p_queue.get()
+
+ def p_poll(self, timeout=0.1):
+ assert self.p is not None
+ assert self.p_running
+ if self.p_next is not None:
+ return False
+ try:
+ self.p_next = self.p_queue.get(True, timeout)
+ return False
+ except Empty:
+ return True
+
+ def p_close(self):
+ assert self.p is not None
+ self.p.stdin.close()
+ self.p_thread.join()
+ assert not self.p_running
+ del running_solvers[self.p_index]
+ self.p = None
+ self.p_next = None
+ self.p_queue = None
+ self.p_thread = None
+
def write(self, stmt, unroll=True):
if stmt.startswith(";"):
self.info(stmt)
+ if not self.setup_done:
+ self.info_stmts.append(stmt)
+ return
elif not self.setup_done:
self.setup()
stmt = stmt.strip()
if self.nocomments or self.unroll:
- if stmt.startswith(";"):
- return
- stmt = re.sub(r" ;.*", "", stmt)
+ stmt = re.sub(r" *;.*", "", stmt)
+ if stmt == "": return
if unroll and self.unroll:
stmt = self.unroll_buffer + stmt
@@ -271,20 +400,17 @@ class SmtIo:
if self.solver != "dummy":
if self.noincr:
if self.p is not None and not stmt.startswith("(get-"):
- self.p.stdin.close()
- self.p = None
+ self.p_close()
if stmt == "(push 1)":
self.smt2cache.append(list())
elif stmt == "(pop 1)":
self.smt2cache.pop()
else:
if self.p is not None:
- self.p.stdin.write(bytes(stmt + "\n", "ascii"))
- self.p.stdin.flush()
+ self.p_write(stmt + "\n", True)
self.smt2cache[-1].append(stmt)
else:
- self.p.stdin.write(bytes(stmt + "\n", "ascii"))
- self.p.stdin.flush()
+ self.p_write(stmt + "\n", True)
def info(self, stmt):
if not stmt.startswith("; yosys-smt2-"):
@@ -300,6 +426,15 @@ class SmtIo:
if self.logic is None:
self.logic_bv = False
+ if fields[1] == "yosys-smt2-stdt":
+ if self.logic is None:
+ self.logic_dt = True
+
+ if fields[1] == "yosys-smt2-forall":
+ if self.logic is None:
+ self.logic_qf = False
+ self.forall = True
+
if fields[1] == "yosys-smt2-module":
self.curmod = fields[2]
self.modinfo[self.curmod] = SmtModInfo()
@@ -323,17 +458,40 @@ class SmtIo:
self.modinfo[self.curmod].wsize[fields[2]] = int(fields[3])
if fields[1] == "yosys-smt2-memory":
- self.modinfo[self.curmod].memories[fields[2]] = (int(fields[3]), int(fields[4]), int(fields[5]))
+ self.modinfo[self.curmod].memories[fields[2]] = (int(fields[3]), int(fields[4]), int(fields[5]), int(fields[6]), fields[7] == "async")
if fields[1] == "yosys-smt2-wire":
self.modinfo[self.curmod].wires.add(fields[2])
self.modinfo[self.curmod].wsize[fields[2]] = int(fields[3])
+ if fields[1] == "yosys-smt2-clock":
+ for edge in fields[3:]:
+ if fields[2] not in self.modinfo[self.curmod].clocks:
+ self.modinfo[self.curmod].clocks[fields[2]] = edge
+ elif self.modinfo[self.curmod].clocks[fields[2]] != edge:
+ self.modinfo[self.curmod].clocks[fields[2]] = "event"
+
if fields[1] == "yosys-smt2-assert":
- self.modinfo[self.curmod].asserts[fields[2]] = fields[3]
+ self.modinfo[self.curmod].asserts["%s_a %s" % (self.curmod, fields[2])] = fields[3]
+
+ if fields[1] == "yosys-smt2-cover":
+ self.modinfo[self.curmod].covers["%s_c %s" % (self.curmod, fields[2])] = fields[3]
if fields[1] == "yosys-smt2-anyconst":
- self.modinfo[self.curmod].anyconsts[fields[2]] = fields[3]
+ self.modinfo[self.curmod].anyconsts[fields[2]] = (fields[4], None if len(fields) <= 5 else fields[5])
+ self.modinfo[self.curmod].asize[fields[2]] = int(fields[3])
+
+ if fields[1] == "yosys-smt2-anyseq":
+ self.modinfo[self.curmod].anyseqs[fields[2]] = (fields[4], None if len(fields) <= 5 else fields[5])
+ self.modinfo[self.curmod].asize[fields[2]] = int(fields[3])
+
+ if fields[1] == "yosys-smt2-allconst":
+ self.modinfo[self.curmod].allconsts[fields[2]] = (fields[4], None if len(fields) <= 5 else fields[5])
+ self.modinfo[self.curmod].asize[fields[2]] = int(fields[3])
+
+ if fields[1] == "yosys-smt2-allseq":
+ self.modinfo[self.curmod].allseqs[fields[2]] = (fields[4], None if len(fields) <= 5 else fields[5])
+ self.modinfo[self.curmod].asize[fields[2]] = int(fields[3])
def hiernets(self, top, regs_only=False):
def hiernets_worker(nets, mod, cursor):
@@ -347,6 +505,54 @@ class SmtIo:
hiernets_worker(nets, top, [])
return nets
+ def hieranyconsts(self, top):
+ def worker(results, mod, cursor):
+ for name, value in sorted(self.modinfo[mod].anyconsts.items()):
+ width = self.modinfo[mod].asize[name]
+ results.append((cursor, name, value[0], value[1], width))
+ for cellname, celltype in sorted(self.modinfo[mod].cells.items()):
+ worker(results, celltype, cursor + [cellname])
+
+ results = list()
+ worker(results, top, [])
+ return results
+
+ def hieranyseqs(self, top):
+ def worker(results, mod, cursor):
+ for name, value in sorted(self.modinfo[mod].anyseqs.items()):
+ width = self.modinfo[mod].asize[name]
+ results.append((cursor, name, value[0], value[1], width))
+ for cellname, celltype in sorted(self.modinfo[mod].cells.items()):
+ worker(results, celltype, cursor + [cellname])
+
+ results = list()
+ worker(results, top, [])
+ return results
+
+ def hierallconsts(self, top):
+ def worker(results, mod, cursor):
+ for name, value in sorted(self.modinfo[mod].allconsts.items()):
+ width = self.modinfo[mod].asize[name]
+ results.append((cursor, name, value[0], value[1], width))
+ for cellname, celltype in sorted(self.modinfo[mod].cells.items()):
+ worker(results, celltype, cursor + [cellname])
+
+ results = list()
+ worker(results, top, [])
+ return results
+
+ def hierallseqs(self, top):
+ def worker(results, mod, cursor):
+ for name, value in sorted(self.modinfo[mod].allseqs.items()):
+ width = self.modinfo[mod].asize[name]
+ results.append((cursor, name, value[0], value[1], width))
+ for cellname, celltype in sorted(self.modinfo[mod].cells.items()):
+ worker(results, celltype, cursor + [cellname])
+
+ results = list()
+ worker(results, top, [])
+ return results
+
def hiermems(self, top):
def hiermems_worker(mems, mod, cursor):
for memname in sorted(self.modinfo[mod].memories.keys()):
@@ -366,7 +572,7 @@ class SmtIo:
if self.solver == "dummy":
line = self.dummy_fd.readline().strip()
else:
- line = self.p.stdout.readline().decode("ascii").strip()
+ line = self.p_read().strip()
if self.dummy_file is not None:
self.dummy_fd.write(line + "\n")
@@ -379,12 +585,14 @@ class SmtIo:
if count_brackets == 0:
break
if self.solver != "dummy" and self.p.poll():
- print("SMT Solver terminated unexpectedly: %s" % "".join(stmt))
+ print("%s Solver terminated unexpectedly: %s" % (self.timestamp(), "".join(stmt)), flush=True)
sys.exit(1)
stmt = "".join(stmt)
if stmt.startswith("(error"):
- print("SMT Solver Error: %s" % stmt, file=sys.stderr)
+ print("%s Solver Error: %s" % (self.timestamp(), stmt), flush=True)
+ if self.solver != "dummy":
+ self.p_close()
sys.exit(1)
return stmt
@@ -399,15 +607,13 @@ class SmtIo:
if self.solver != "dummy":
if self.noincr:
if self.p is not None:
- self.p.stdin.close()
- self.p = None
- self.p = subprocess.Popen(self.popen_vargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ self.p_close()
+ self.p_open()
for cache_ctx in self.smt2cache:
for cache_stmt in cache_ctx:
- self.p.stdin.write(bytes(cache_stmt + "\n", "ascii"))
+ self.p_write(cache_stmt + "\n", False)
- self.p.stdin.write(bytes("(check-sat)\n", "ascii"))
- self.p.stdin.flush()
+ self.p_write("(check-sat)\n", True)
if self.timeinfo:
i = 0
@@ -415,7 +621,7 @@ class SmtIo:
count = 0
num_bs = 0
- while select([self.p.stdout], [], [], 0.1) == ([], [], []):
+ while self.p_poll():
count += 1
if count < 25:
@@ -444,11 +650,43 @@ class SmtIo:
print("\b \b" * num_bs, end="", file=sys.stderr)
sys.stderr.flush()
+ else:
+ count = 0
+ while self.p_poll(60):
+ count += 1
+ msg = None
+
+ if count == 1:
+ msg = "1 minute"
+
+ elif count in [5, 10, 15, 30]:
+ msg = "%d minutes" % count
+
+ elif count == 60:
+ msg = "1 hour"
+
+ elif count % 60 == 0:
+ msg = "%d hours" % (count // 60)
+
+ if msg is not None:
+ print("%s waiting for solver (%s)" % (self.timestamp(), msg), flush=True)
+
result = self.read()
+
if self.debug_file:
print("(set-info :status %s)" % result, file=self.debug_file)
print("(check-sat)", file=self.debug_file)
self.debug_file.flush()
+
+ if result not in ["sat", "unsat"]:
+ if result == "":
+ print("%s Unexpected EOF response from solver." % (self.timestamp()), flush=True)
+ else:
+ print("%s Unexpected response from solver: %s" % (self.timestamp(), result), flush=True)
+ if self.solver != "dummy":
+ self.p_close()
+ sys.exit(1)
+
return result
def parse(self, stmt):
@@ -503,6 +741,9 @@ class SmtIo:
return h
def bv2bin(self, v):
+ if type(v) is list and len(v) == 3 and v[0] == "_" and v[1].startswith("bv"):
+ x, n = int(v[1][2:]), int(v[2])
+ return "".join("1" if (x & (1 << i)) else "0" for i in range(n-1, -1, -1))
if v == "true": return "1"
if v == "false": return "0"
if v.startswith("#b"):
@@ -539,6 +780,9 @@ class SmtIo:
return [".".join(path)]
def net_expr(self, mod, base, path):
+ if len(path) == 0:
+ return base
+
if len(path) == 1:
assert mod in self.modinfo
if path[0] == "":
@@ -568,23 +812,54 @@ class SmtIo:
assert net_path[-1] in self.modinfo[mod].wsize
return self.modinfo[mod].wsize[net_path[-1]]
- def mem_expr(self, mod, base, path, portidx=None, infomode=False):
+ def net_clock(self, mod, net_path):
+ for i in range(len(net_path)-1):
+ assert mod in self.modinfo
+ assert net_path[i] in self.modinfo[mod].cells
+ mod = self.modinfo[mod].cells[net_path[i]]
+
+ assert mod in self.modinfo
+ if net_path[-1] not in self.modinfo[mod].clocks:
+ return None
+ return self.modinfo[mod].clocks[net_path[-1]]
+
+ def net_exists(self, mod, net_path):
+ for i in range(len(net_path)-1):
+ if mod not in self.modinfo: return False
+ if net_path[i] not in self.modinfo[mod].cells: return False
+ mod = self.modinfo[mod].cells[net_path[i]]
+
+ if mod not in self.modinfo: return False
+ if net_path[-1] not in self.modinfo[mod].wsize: return False
+ return True
+
+ def mem_exists(self, mod, mem_path):
+ for i in range(len(mem_path)-1):
+ if mod not in self.modinfo: return False
+ if mem_path[i] not in self.modinfo[mod].cells: return False
+ mod = self.modinfo[mod].cells[mem_path[i]]
+
+ if mod not in self.modinfo: return False
+ if mem_path[-1] not in self.modinfo[mod].memories: return False
+ return True
+
+ def mem_expr(self, mod, base, path, port=None, infomode=False):
if len(path) == 1:
assert mod in self.modinfo
assert path[0] in self.modinfo[mod].memories
if infomode:
return self.modinfo[mod].memories[path[0]]
- return "(|%s_m%s %s| %s)" % (mod, "" if portidx is None else ":%d" % portidx, path[0], base)
+ return "(|%s_m%s %s| %s)" % (mod, "" if port is None else ":%s" % port, path[0], base)
assert mod in self.modinfo
assert path[0] in self.modinfo[mod].cells
nextmod = self.modinfo[mod].cells[path[0]]
nextbase = "(|%s_h %s| %s)" % (mod, path[0], base)
- return self.mem_expr(nextmod, nextbase, path[1:], portidx=portidx, infomode=infomode)
+ return self.mem_expr(nextmod, nextbase, path[1:], port=port, infomode=infomode)
- def mem_info(self, mod, base, path):
- return self.mem_expr(mod, base, path, infomode=True)
+ def mem_info(self, mod, path):
+ return self.mem_expr(mod, "", path, infomode=True)
def get_net(self, mod_name, net_path, state_name):
return self.get(self.net_expr(mod_name, state_name, net_path))
@@ -607,19 +882,21 @@ class SmtIo:
def wait(self):
if self.p is not None:
self.p.wait()
+ self.p_close()
class SmtOpts:
def __init__(self):
- self.shortopts = "s:v"
+ self.shortopts = "s:S:v"
self.longopts = ["unroll", "noincr", "noprogress", "dump-smt2=", "logic=", "dummy=", "info=", "nocomments"]
- self.solver = "z3"
+ self.solver = "yices"
+ self.solver_opts = list()
self.debug_print = False
self.debug_file = None
self.dummy_file = None
self.unroll = False
self.noincr = False
- self.timeinfo = True
+ self.timeinfo = os.name != "nt"
self.logic = None
self.info_stmts = list()
self.nocomments = False
@@ -627,6 +904,8 @@ class SmtOpts:
def handle(self, o, a):
if o == "-s":
self.solver = a
+ elif o == "-S":
+ self.solver_opts.append(a)
elif o == "-v":
self.debug_print = True
elif o == "--unroll":
@@ -634,7 +913,7 @@ class SmtOpts:
elif o == "--noincr":
self.noincr = True
elif o == "--noprogress":
- self.timeinfo = True
+ self.timeinfo = False
elif o == "--dump-smt2":
self.debug_file = open(a, "w")
elif o == "--logic":
@@ -652,8 +931,11 @@ class SmtOpts:
def helpmsg(self):
return """
-s <solver>
- set SMT solver: z3, cvc4, yices, mathsat, boolector, dummy
- default: z3
+ set SMT solver: z3, yices, boolector, cvc4, mathsat, dummy
+ default: yices
+
+ -S <opt>
+ pass <opt> as command line argument to the solver
--logic <smt2_logic>
use the specified SMT2 logic (e.g. QF_AUFBV)
@@ -674,6 +956,7 @@ class SmtOpts:
--noprogress
disable timer display during solving
+ (this option is set implicitly on Windows)
--dump-smt2 <filename>
write smt2 statements to file
@@ -691,6 +974,7 @@ class MkVcd:
self.f = f
self.t = -1
self.nets = dict()
+ self.clocks = dict()
def add_net(self, path, width):
path = tuple(path)
@@ -698,11 +982,25 @@ class MkVcd:
key = "n%d" % len(self.nets)
self.nets[path] = (key, width)
+ def add_clock(self, path, edge):
+ path = tuple(path)
+ assert self.t == -1
+ key = "n%d" % len(self.nets)
+ self.nets[path] = (key, 1)
+ self.clocks[path] = (key, edge)
+
def set_net(self, path, bits):
path = tuple(path)
assert self.t >= 0
assert path in self.nets
- print("b%s %s" % (bits, self.nets[path][0]), file=self.f)
+ if path not in self.clocks:
+ print("b%s %s" % (bits, self.nets[path][0]), file=self.f)
+
+ def escape_name(self, name):
+ name = re.sub(r"\[([0-9a-zA-Z_]*[a-zA-Z_][0-9a-zA-Z_]*)\]", r"<\1>", name)
+ if re.match("[\[\]]", name) and name[0] != "\\":
+ name = "\\" + name
+ return name
def set_time(self, t):
assert t >= self.t
@@ -710,22 +1008,52 @@ class MkVcd:
if self.t == -1:
print("$var integer 32 t smt_step $end", file=self.f)
print("$var event 1 ! smt_clock $end", file=self.f)
+
scope = []
for path in sorted(self.nets):
- while len(scope)+1 > len(path) or (len(scope) > 0 and scope[-1] != path[len(scope)-1]):
+ key, width = self.nets[path]
+
+ uipath = list(path)
+ if "." in uipath[-1]:
+ uipath = uipath[0:-1] + uipath[-1].split(".")
+ for i in range(len(uipath)):
+ uipath[i] = re.sub(r"\[([^\]]*)\]", r"<\1>", uipath[i])
+
+ while uipath[:len(scope)] != scope:
print("$upscope $end", file=self.f)
scope = scope[:-1]
- while len(scope)+1 < len(path):
- print("$scope module %s $end" % path[len(scope)], file=self.f)
- scope.append(path[len(scope)-1])
- key, width = self.nets[path]
- print("$var wire %d %s %s $end" % (width, key, path[-1]), file=self.f)
+
+ while uipath[:-1] != scope:
+ print("$scope module %s $end" % uipath[len(scope)], file=self.f)
+ scope.append(uipath[len(scope)])
+
+ if path in self.clocks and self.clocks[path][1] == "event":
+ print("$var event 1 %s %s $end" % (key, uipath[-1]), file=self.f)
+ else:
+ print("$var wire %d %s %s $end" % (width, key, uipath[-1]), file=self.f)
+
for i in range(len(scope)):
print("$upscope $end", file=self.f)
+
print("$enddefinitions $end", file=self.f)
+
self.t = t
assert self.t >= 0
+
+ if self.t > 0:
+ print("#%d" % (10 * self.t - 5), file=self.f)
+ for path in sorted(self.clocks.keys()):
+ if self.clocks[path][1] == "posedge":
+ print("b0 %s" % self.nets[path][0], file=self.f)
+ elif self.clocks[path][1] == "negedge":
+ print("b1 %s" % self.nets[path][0], file=self.f)
+
print("#%d" % (10 * self.t), file=self.f)
print("1!", file=self.f)
print("b%s t" % format(self.t, "032b"), file=self.f)
+ for path in sorted(self.clocks.keys()):
+ if self.clocks[path][1] == "negedge":
+ print("b0 %s" % self.nets[path][0], file=self.f)
+ else:
+ print("b1 %s" % self.nets[path][0], file=self.f)
diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc
index 162ce490..b8383412 100644
--- a/backends/smv/smv.cc
+++ b/backends/smv/smv.cc
@@ -507,15 +507,19 @@ struct SmvWorker
continue;
}
- if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_"))
+ if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_"))
{
string op;
- if (cell->type.in("$_AND_", "$_NAND_")) op = "&";
- if (cell->type.in("$_OR_", "$_NOR_")) op = "|";
+ if (cell->type.in("$_AND_", "$_NAND_", "$_ANDNOT_")) op = "&";
+ if (cell->type.in("$_OR_", "$_NOR_", "$_ORNOT_")) op = "|";
if (cell->type.in("$_XOR_")) op = "xor";
if (cell->type.in("$_XNOR_")) op = "xnor";
+ if (cell->type.in("$_ANDNOT_", "$_ORNOT_"))
+ assignments.push_back(stringf("%s := %s %s (!%s);", lvalue(cell->getPort("\\Y")),
+ rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B"))));
+ else
if (cell->type.in("$_NAND_", "$_NOR_"))
assignments.push_back(stringf("%s := !(%s %s %s);", lvalue(cell->getPort("\\Y")),
rvalue(cell->getPort("\\A")), op.c_str(), rvalue(cell->getPort("\\B"))));
@@ -671,7 +675,7 @@ struct SmvWorker
struct SmvBackend : public Backend {
SmvBackend() : Backend("smv", "write design to SMV file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -689,7 +693,7 @@ struct SmvBackend : public Backend {
log("THIS COMMAND IS UNDER CONSTRUCTION\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::ifstream template_f;
bool verbose = false;
diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc
index 4101cbf9..b6a3f1e7 100644
--- a/backends/spice/spice.cc
+++ b/backends/spice/spice.cc
@@ -132,7 +132,7 @@ static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::De
struct SpiceBackend : public Backend {
SpiceBackend() : Backend("spice", "write design to SPICE netlist file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -161,7 +161,7 @@ struct SpiceBackend : public Backend {
log(" set the specified module as design top module\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
std::string top_module_name;
RTLIL::Module *top_module = NULL;
diff --git a/backends/table/Makefile.inc b/backends/table/Makefile.inc
new file mode 100644
index 00000000..8cd1dc61
--- /dev/null
+++ b/backends/table/Makefile.inc
@@ -0,0 +1,3 @@
+
+OBJS += backends/table/table.o
+
diff --git a/backends/table/table.cc b/backends/table/table.cc
new file mode 100644
index 00000000..979273dd
--- /dev/null
+++ b/backends/table/table.cc
@@ -0,0 +1,120 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/rtlil.h"
+#include "kernel/register.h"
+#include "kernel/sigtools.h"
+#include "kernel/celltypes.h"
+#include "kernel/log.h"
+#include <string>
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct TableBackend : public Backend {
+ TableBackend() : Backend("table", "write design as connectivity table") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" write_table [options] [filename]\n");
+ log("\n");
+ log("Write the current design as connectivity table. The output is a tab-separated\n");
+ log("ASCII table with the following columns:\n");
+ log("\n");
+ log(" module name\n");
+ log(" cell name\n");
+ log(" cell type\n");
+ log(" cell port\n");
+ log(" direction\n");
+ log(" signal\n");
+ log("\n");
+ log("module inputs and outputs are output using cell type and port '-' and with\n");
+ log("'pi' (primary input) or 'po' (primary output) or 'pio' as direction.\n");
+ }
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ log_header(design, "Executing TABLE backend.\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // if (args[argidx] == "-top" && argidx+1 < args.size()) {
+ // top_module_name = args[++argidx];
+ // continue;
+ // }
+ break;
+ }
+ extra_args(f, filename, args, argidx);
+
+ design->sort();
+
+ for (auto module : design->modules())
+ {
+ if (module->get_bool_attribute("\\blackbox"))
+ continue;
+
+ SigMap sigmap(module);
+
+ for (auto wire : module->wires())
+ {
+ if (wire->port_id == 0)
+ continue;
+
+ *f << log_id(module) << "\t";
+ *f << log_id(wire) << "\t";
+ *f << "-" << "\t";
+ *f << "-" << "\t";
+
+ if (wire->port_input && wire->port_output)
+ *f << "pio" << "\t";
+ else if (wire->port_input)
+ *f << "pi" << "\t";
+ else if (wire->port_output)
+ *f << "po" << "\t";
+ else
+ log_abort();
+
+ *f << log_signal(sigmap(wire)) << "\n";
+ }
+
+ for (auto cell : module->cells())
+ for (auto conn : cell->connections())
+ {
+ *f << log_id(module) << "\t";
+ *f << log_id(cell) << "\t";
+ *f << log_id(cell->type) << "\t";
+ *f << log_id(conn.first) << "\t";
+
+ if (cell->input(conn.first) && cell->output(conn.first))
+ *f << "inout" << "\t";
+ else if (cell->input(conn.first))
+ *f << "in" << "\t";
+ else if (cell->output(conn.first))
+ *f << "out" << "\t";
+ else
+ *f << "unkown" << "\t";
+
+ *f << log_signal(sigmap(conn.second)) << "\n";
+ }
+ }
+ }
+} TableBackend;
+
+PRIVATE_NAMESPACE_END
diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc
index a617215f..44e4e5f9 100644
--- a/backends/verilog/verilog_backend.cc
+++ b/backends/verilog/verilog_backend.cc
@@ -33,13 +33,15 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-bool verbose, norename, noattr, attr2comment, noexpr, nodec, nostr, defparam;
+bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, defparam, decimal;
int auto_name_counter, auto_name_offset, auto_name_digits;
std::map<RTLIL::IdString, int> auto_name_map;
std::set<RTLIL::IdString> reg_wires, reg_ct;
std::string auto_prefix;
RTLIL::Module *active_module;
+dict<RTLIL::SigBit, RTLIL::State> active_initdata;
+SigMap active_sigmap;
void reset_auto_counter_id(RTLIL::IdString id, bool may_rename)
{
@@ -159,23 +161,73 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
if (width < 0)
width = data.bits.size() - offset;
if (nostr)
- goto dump_bits;
+ goto dump_hex;
if ((data.flags & RTLIL::CONST_FLAG_STRING) == 0 || width != (int)data.bits.size()) {
if (width == 32 && !no_decimal && !nodec) {
int32_t val = 0;
for (int i = offset+width-1; i >= offset; i--) {
log_assert(i < (int)data.bits.size());
if (data.bits[i] != RTLIL::S0 && data.bits[i] != RTLIL::S1)
- goto dump_bits;
+ goto dump_hex;
if (data.bits[i] == RTLIL::S1)
val |= 1 << (i - offset);
}
- if (set_signed && val < 0)
+ if (decimal)
+ f << stringf("%d", val);
+ else if (set_signed && val < 0)
f << stringf("-32'sd%u", -val);
else
f << stringf("32'%sd%u", set_signed ? "s" : "", val);
} else {
- dump_bits:
+ dump_hex:
+ if (nohex)
+ goto dump_bin;
+ vector<char> bin_digits, hex_digits;
+ for (int i = offset; i < offset+width; i++) {
+ log_assert(i < (int)data.bits.size());
+ switch (data.bits[i]) {
+ case RTLIL::S0: bin_digits.push_back('0'); break;
+ case RTLIL::S1: bin_digits.push_back('1'); break;
+ case RTLIL::Sx: bin_digits.push_back('x'); break;
+ case RTLIL::Sz: bin_digits.push_back('z'); break;
+ case RTLIL::Sa: bin_digits.push_back('z'); break;
+ case RTLIL::Sm: log_error("Found marker state in final netlist.");
+ }
+ }
+ if (GetSize(bin_digits) == 0)
+ goto dump_bin;
+ while (GetSize(bin_digits) % 4 != 0)
+ if (bin_digits.back() == '1')
+ bin_digits.push_back('0');
+ else
+ bin_digits.push_back(bin_digits.back());
+ for (int i = 0; i < GetSize(bin_digits); i += 4)
+ {
+ char bit_3 = bin_digits[i+3];
+ char bit_2 = bin_digits[i+2];
+ char bit_1 = bin_digits[i+1];
+ char bit_0 = bin_digits[i+0];
+ if (bit_3 == 'x' || bit_2 == 'x' || bit_1 == 'x' || bit_0 == 'x') {
+ if (bit_3 != 'x' || bit_2 != 'x' || bit_1 != 'x' || bit_0 != 'x')
+ goto dump_bin;
+ hex_digits.push_back('x');
+ continue;
+ }
+ if (bit_3 == 'z' || bit_2 == 'z' || bit_1 == 'z' || bit_0 == 'z') {
+ if (bit_3 != 'z' || bit_2 != 'z' || bit_1 != 'z' || bit_0 != 'z')
+ goto dump_bin;
+ hex_digits.push_back('z');
+ continue;
+ }
+ int val = 8*(bit_3 - '0') + 4*(bit_2 - '0') + 2*(bit_1 - '0') + (bit_0 - '0');
+ hex_digits.push_back(val < 10 ? '0' + val : 'a' + val - 10);
+ }
+ f << stringf("%d'%sh", width, set_signed ? "s" : "");
+ for (int i = GetSize(hex_digits)-1; i >= 0; i--)
+ f << hex_digits[i];
+ }
+ if (0) {
+ dump_bin:
f << stringf("%d'%sb", width, set_signed ? "s" : "");
if (width == 0)
f << stringf("0");
@@ -214,6 +266,26 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
}
}
+void dump_reg_init(std::ostream &f, SigSpec sig)
+{
+ Const initval;
+ bool gotinit = false;
+
+ for (auto bit : active_sigmap(sig)) {
+ if (active_initdata.count(bit)) {
+ initval.bits.push_back(active_initdata.at(bit));
+ gotinit = true;
+ } else {
+ initval.bits.push_back(State::Sx);
+ }
+ }
+
+ if (gotinit) {
+ f << " = ";
+ dump_const(f, initval);
+ }
+}
+
void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool no_decimal = false)
{
if (chunk.wire == NULL) {
@@ -302,12 +374,12 @@ void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire)
if (wire->port_input && wire->port_output)
f << stringf("%s" "inout%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
if (reg_wires.count(wire->name)) {
- f << stringf("%s" "reg%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
+ f << stringf("%s" "reg%s %s", indent.c_str(), range.c_str(), id(wire->name).c_str());
if (wire->attributes.count("\\init")) {
- f << stringf("%s" "initial %s = ", indent.c_str(), id(wire->name).c_str());
+ f << stringf(" = ");
dump_const(f, wire->attributes.at("\\init"));
- f << stringf(";\n");
}
+ f << stringf(";\n");
} else if (!wire->port_input && !wire->port_output)
f << stringf("%s" "wire%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
#endif
@@ -400,7 +472,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
return true;
}
- if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_")) {
+ if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_")) {
f << stringf("%s" "assign ", indent.c_str());
dump_sigspec(f, cell->getPort("\\Y"));
f << stringf(" = ");
@@ -408,16 +480,18 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
f << stringf("~(");
dump_cell_expr_port(f, cell, "A", false);
f << stringf(" ");
- if (cell->type.in("$_AND_", "$_NAND_"))
+ if (cell->type.in("$_AND_", "$_NAND_", "$_ANDNOT_"))
f << stringf("&");
- if (cell->type.in("$_OR_", "$_NOR_"))
+ if (cell->type.in("$_OR_", "$_NOR_", "$_ORNOT_"))
f << stringf("|");
if (cell->type.in("$_XOR_", "$_XNOR_"))
f << stringf("^");
dump_attributes(f, "", cell->attributes, ' ');
f << stringf(" ");
+ if (cell->type.in("$_ANDNOT_", "$_ORNOT_"))
+ f << stringf("~(");
dump_cell_expr_port(f, cell, "B", false);
- if (cell->type.in("$_NAND_", "$_NOR_", "$_XNOR_"))
+ if (cell->type.in("$_NAND_", "$_NOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_"))
f << stringf(")");
f << stringf(";\n");
return true;
@@ -474,8 +548,11 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
std::string reg_name = cellname(cell);
bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name);
- if (!out_is_reg_wire)
- f << stringf("%s" "reg %s;\n", indent.c_str(), reg_name.c_str());
+ if (!out_is_reg_wire) {
+ f << stringf("%s" "reg %s", indent.c_str(), reg_name.c_str());
+ dump_reg_init(f, cell->getPort("\\Q"));
+ f << ";\n";
+ }
dump_attributes(f, indent, cell->attributes);
f << stringf("%s" "always @(%sedge ", indent.c_str(), cell->type[6] == 'P' ? "pos" : "neg");
@@ -514,8 +591,11 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
std::string reg_name = cellname(cell);
bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name);
- if (!out_is_reg_wire)
- f << stringf("%s" "reg %s;\n", indent.c_str(), reg_name.c_str());
+ if (!out_is_reg_wire) {
+ f << stringf("%s" "reg %s", indent.c_str(), reg_name.c_str());
+ dump_reg_init(f, cell->getPort("\\Q"));
+ f << ";\n";
+ }
dump_attributes(f, indent, cell->attributes);
f << stringf("%s" "always @(%sedge ", indent.c_str(), pol_c == 'P' ? "pos" : "neg");
@@ -598,6 +678,23 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
#undef HANDLE_UNIOP
#undef HANDLE_BINOP
+ if (cell->type == "$shiftx")
+ {
+ f << stringf("%s" "assign ", indent.c_str());
+ dump_sigspec(f, cell->getPort("\\Y"));
+ f << stringf(" = ");
+ dump_sigspec(f, cell->getPort("\\A"));
+ f << stringf("[");
+ if (cell->getParam("\\B_SIGNED").as_bool())
+ f << stringf("$signed(");
+ dump_sigspec(f, cell->getPort("\\B"));
+ if (cell->getParam("\\B_SIGNED").as_bool())
+ f << stringf(")");
+ f << stringf(" +: %d", cell->getParam("\\Y_WIDTH").as_int());
+ f << stringf("];\n");
+ return true;
+ }
+
if (cell->type == "$mux")
{
f << stringf("%s" "assign ", indent.c_str());
@@ -698,8 +795,11 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
std::string reg_name = cellname(cell);
bool out_is_reg_wire = is_reg_wire(sig_q, reg_name);
- if (!out_is_reg_wire)
- f << stringf("%s" "reg [%d:0] %s;\n", indent.c_str(), width-1, reg_name.c_str());
+ if (!out_is_reg_wire) {
+ f << stringf("%s" "reg [%d:0] %s", indent.c_str(), width-1, reg_name.c_str());
+ dump_reg_init(f, sig_q);
+ f << ";\n";
+ }
for (int i = 0; i < width; i++) {
f << stringf("%s" "always @(%sedge ", indent.c_str(), pol_clk ? "pos" : "neg");
@@ -754,8 +854,11 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
std::string reg_name = cellname(cell);
bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name);
- if (!out_is_reg_wire)
- f << stringf("%s" "reg [%d:0] %s;\n", indent.c_str(), cell->parameters["\\WIDTH"].as_int()-1, reg_name.c_str());
+ if (!out_is_reg_wire) {
+ f << stringf("%s" "reg [%d:0] %s", indent.c_str(), cell->parameters["\\WIDTH"].as_int()-1, reg_name.c_str());
+ dump_reg_init(f, cell->getPort("\\Q"));
+ f << ";\n";
+ }
f << stringf("%s" "always @(%sedge ", indent.c_str(), pol_clk ? "pos" : "neg");
dump_sigspec(f, sig_clk);
@@ -794,6 +897,42 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
return true;
}
+ if (cell->type == "$dlatch")
+ {
+ RTLIL::SigSpec sig_en;
+ bool pol_en = false;
+
+ sig_en = cell->getPort("\\EN");
+ pol_en = cell->parameters["\\EN_POLARITY"].as_bool();
+
+ std::string reg_name = cellname(cell);
+ bool out_is_reg_wire = is_reg_wire(cell->getPort("\\Q"), reg_name);
+
+ if (!out_is_reg_wire) {
+ f << stringf("%s" "reg [%d:0] %s", indent.c_str(), cell->parameters["\\WIDTH"].as_int()-1, reg_name.c_str());
+ dump_reg_init(f, cell->getPort("\\Q"));
+ f << ";\n";
+ }
+
+ f << stringf("%s" "always @*\n", indent.c_str());
+
+ f << stringf("%s" " if (%s", indent.c_str(), pol_en ? "" : "!");
+ dump_sigspec(f, sig_en);
+ f << stringf(")\n");
+
+ f << stringf("%s" " %s = ", indent.c_str(), reg_name.c_str());
+ dump_cell_expr_port(f, cell, "D", false);
+ f << stringf(";\n");
+
+ if (!out_is_reg_wire) {
+ f << stringf("%s" "assign ", indent.c_str());
+ dump_sigspec(f, cell->getPort("\\Q"));
+ f << stringf(" = %s;\n", reg_name.c_str());
+ }
+
+ return true;
+ }
+
if (cell->type == "$mem")
{
RTLIL::IdString memid = cell->parameters["\\MEMID"].decode_string();
@@ -806,7 +945,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
// for memory block make something like:
// reg [7:0] memid [3:0];
// initial begin
- // memid[0] <= ...
+ // memid[0] = ...
// end
f << stringf("%s" "reg [%d:%d] %s [%d:%d];\n", indent.c_str(), width-1, 0, mem_id.c_str(), size-1, 0);
if (use_init)
@@ -814,7 +953,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
f << stringf("%s" "initial begin\n", indent.c_str());
for (int i=0; i<size; i++)
{
- f << stringf("%s" " %s[%d] <= ", indent.c_str(), mem_id.c_str(), i);
+ f << stringf("%s" " %s[%d] = ", indent.c_str(), mem_id.c_str(), i);
dump_const(f, cell->parameters["\\INIT"].extract(i*width, width));
f << stringf(";\n");
}
@@ -912,7 +1051,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
int nwrite_ports = cell->parameters["\\WR_PORTS"].as_int();
RTLIL::SigSpec sig_wr_clk, sig_wr_data, sig_wr_addr, sig_wr_en;
bool wr_clk_posedge;
- SigMap sigmap(active_module);
+
// write ports
for (int i=0; i < nwrite_ports; i++)
{
@@ -937,7 +1076,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
int start_i = i, width = 1;
SigBit wen_bit = sig_wr_en[i];
- while (i+1 < GetSize(sig_wr_en) && sigmap(sig_wr_en[i+1]) == sigmap(wen_bit))
+ while (i+1 < GetSize(sig_wr_en) && active_sigmap(sig_wr_en[i+1]) == active_sigmap(wen_bit))
i++, width++;
if (wen_bit == State::S0)
@@ -1251,6 +1390,16 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
reg_wires.clear();
reset_auto_counter(module);
active_module = module;
+ active_sigmap.set(module);
+ active_initdata.clear();
+
+ for (auto wire : module->wires())
+ if (wire->attributes.count("\\init")) {
+ SigSpec sig = active_sigmap(wire);
+ Const val = wire->attributes.at("\\init");
+ for (int i = 0; i < GetSize(sig) && i < GetSize(val); i++)
+ active_initdata[sig[i]] = val.bits.at(i);
+ }
if (!module->processes.empty())
log_warning("Module %s contains unmapped RTLIL proccesses. RTLIL processes\n"
@@ -1327,11 +1476,13 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
f << stringf("%s" "endmodule\n", indent.c_str());
active_module = NULL;
+ active_sigmap.clear();
+ active_initdata.clear();
}
struct VerilogBackend : public Backend {
VerilogBackend() : Backend("verilog", "write design to Verilog file") { }
- virtual void help()
+ void help() YS_OVERRIDE
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
@@ -1362,6 +1513,14 @@ struct VerilogBackend : public Backend {
log(" not bit pattern. This option decativates this feature and instead\n");
log(" will write out all constants in binary.\n");
log("\n");
+ log(" -decimal\n");
+ log(" dump 32-bit constants in decimal and without size and radix\n");
+ log("\n");
+ log(" -nohex\n");
+ log(" constant values that are compatible with hex output are usually\n");
+ log(" dumped as hex values. This option decativates this feature and\n");
+ log(" instead will write out all constants in binary.\n");
+ log("\n");
log(" -nostr\n");
log(" Parameters and attributes that are specified as strings in the\n");
log(" original input will be output as strings by this back-end. This\n");
@@ -1391,7 +1550,7 @@ struct VerilogBackend : public Backend {
log("this command is called on a design with RTLIL processes.\n");
log("\n");
}
- virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+ void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing Verilog backend.\n");
@@ -1401,8 +1560,10 @@ struct VerilogBackend : public Backend {
attr2comment = false;
noexpr = false;
nodec = false;
+ nohex = false;
nostr = false;
defparam = false;
+ decimal = false;
auto_prefix = "";
bool blackboxes = false;
@@ -1412,6 +1573,8 @@ struct VerilogBackend : public Backend {
reg_ct.insert("$dff");
reg_ct.insert("$adff");
+ reg_ct.insert("$dffe");
+ reg_ct.insert("$dlatch");
reg_ct.insert("$_DFF_N_");
reg_ct.insert("$_DFF_P_");
@@ -1461,6 +1624,10 @@ struct VerilogBackend : public Backend {
nodec = true;
continue;
}
+ if (arg == "-nohex") {
+ nohex = true;
+ continue;
+ }
if (arg == "-nostr") {
nostr = true;
continue;
@@ -1469,6 +1636,10 @@ struct VerilogBackend : public Backend {
defparam = true;
continue;
}
+ if (arg == "-decimal") {
+ decimal = true;
+ continue;
+ }
if (arg == "-blackboxes") {
blackboxes = true;
continue;
diff --git a/examples/aiger/.gitignore b/examples/aiger/.gitignore
new file mode 100644
index 00000000..3524e936
--- /dev/null
+++ b/examples/aiger/.gitignore
@@ -0,0 +1,5 @@
+demo.aig
+demo.aim
+demo.aiw
+demo.smt2
+demo.vcd
diff --git a/examples/aiger/README b/examples/aiger/README
new file mode 100644
index 00000000..4e7694e9
--- /dev/null
+++ b/examples/aiger/README
@@ -0,0 +1,22 @@
+AIGER is a format for And-Inverter Graphs (AIGs).
+See http://fmv.jku.at/aiger/ for details.
+
+AIGER is used in the Hardware Model Checking Competition (HWMCC),
+therefore all solvers competing in the competition have to support
+the format.
+
+The example in this directory is using super_prove as solver. Check
+http://downloads.bvsrc.org/super_prove/ for the lates release. (See
+https://bitbucket.org/sterin/super_prove_build for sources.)
+
+The "demo.sh" script in this directory expects a "super_prove" executable
+in the PATH. E.g. extract the release to /usr/local/libexec/super_prove
+and then create a /usr/local/bin/super_prove file with the following
+contents (and "chmod +x" that file):
+
+ #!/bin/bash
+ exec /usr/local/libexec/super_prove/bin/super_prove.sh "$@"
+
+The "demo.sh" script also expects the "z3" SMT2 solver in the PATH for
+converting the witness file generated by super_prove to VCD using
+yosys-smtbmc. See https://github.com/Z3Prover/z3 for install notes.
diff --git a/examples/aiger/demo.sh b/examples/aiger/demo.sh
new file mode 100644
index 00000000..8728b672
--- /dev/null
+++ b/examples/aiger/demo.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+set -ex
+yosys -p '
+ read_verilog -formal demo.v
+ prep -flatten -nordff -top demo
+ write_smt2 -wires demo.smt2
+ flatten demo; delete -output
+ memory_map; opt -full
+ techmap; opt -fast
+ abc -fast -g AND; opt_clean
+ write_aiger -map demo.aim demo.aig
+'
+super_prove demo.aig > demo.aiw
+yosys-smtbmc --dump-vcd demo.vcd --aig demo demo.smt2
diff --git a/examples/aiger/demo.v b/examples/aiger/demo.v
new file mode 100644
index 00000000..b9828742
--- /dev/null
+++ b/examples/aiger/demo.v
@@ -0,0 +1,12 @@
+module demo(input clk, reset, ctrl);
+ localparam NBITS = 10;
+ reg [NBITS-1:0] counter;
+ initial counter[NBITS-2] = 0;
+ initial counter[0] = 1;
+ always @(posedge clk) begin
+ counter <= reset ? 1 : ctrl ? counter + 1 : counter - 1;
+ assume(counter != 0);
+ assume(counter != 1 << (NBITS-1));
+ assert(counter != (1 << NBITS)-1);
+ end
+endmodule
diff --git a/examples/basys3/example.xdc b/examples/basys3/example.xdc
index c1fd0e92..8cdaa199 100644
--- a/examples/basys3/example.xdc
+++ b/examples/basys3/example.xdc
@@ -19,3 +19,6 @@ set_property -dict { IOSTANDARD LVCMOS33 PACKAGE_PIN L1 } [get_ports {LD[15]}]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports CLK]
+set_property CONFIG_VOLTAGE 3.3 [current_design]
+set_property CFGBVS VCCO [current_design]
+
diff --git a/examples/basys3/run_prog.tcl b/examples/basys3/run_prog.tcl
index d711af84..b078ad51 100644
--- a/examples/basys3/run_prog.tcl
+++ b/examples/basys3/run_prog.tcl
@@ -1,3 +1,4 @@
+open_hw
connect_hw_server
open_hw_target [lindex [get_hw_targets] 0]
set_property PROGRAM.FILE example.bit [lindex [get_hw_devices] 0]
diff --git a/examples/cmos/counter.ys b/examples/cmos/counter.ys
index a784f346..d0b09366 100644
--- a/examples/cmos/counter.ys
+++ b/examples/cmos/counter.ys
@@ -1,11 +1,12 @@
-
read_verilog counter.v
read_verilog -lib cmos_cells.v
-proc;; memory;; techmap;;
-
+synth
dfflibmap -liberty cmos_cells.lib
-abc -liberty cmos_cells.lib;;
+abc -liberty cmos_cells.lib
+opt_clean
+
+stat -liberty cmos_cells.lib
# http://vlsiarch.ecen.okstate.edu/flows/MOSIS_SCMOS/latest/cadence/lib/tsmc025/signalstorm/osu025_stdcells.lib
# dfflibmap -liberty osu025_stdcells.lib
@@ -13,4 +14,3 @@ abc -liberty cmos_cells.lib;;
write_verilog synth.v
write_spice synth.sp
-
diff --git a/examples/cmos/counter_tb.v b/examples/cmos/counter_tb.v
index bcd7d992..11e82507 100644
--- a/examples/cmos/counter_tb.v
+++ b/examples/cmos/counter_tb.v
@@ -12,7 +12,7 @@ module counter_tb;
# 4 reset = 0;
# 6 $finish;
end
-
+
/* Make enable with period of 8 and 6,7 low */
reg en = 1;
always begin
@@ -25,7 +25,7 @@ module counter_tb;
/* Make a regular pulsing clock. */
reg clk = 0;
always #1 clk = !clk;
-
+
/* UUT */
wire [2:0] count;
counter c1 (clk, reset, en, count);
diff --git a/examples/cmos/testbench_digital.sh b/examples/cmos/testbench_digital.sh
index afaaf4d4..d7ab0fe1 100644
--- a/examples/cmos/testbench_digital.sh
+++ b/examples/cmos/testbench_digital.sh
@@ -4,7 +4,7 @@ set -ex
# iverlog simulation
echo "Doing Verilog simulation with iverilog"
-iverilog -o counter_tb counter.v counter_tb.v
+iverilog -o counter_tb counter.v counter_tb.v
./counter_tb; gtkwave counter_tb.gtkw &
# yosys synthesis
diff --git a/examples/cxx-api/evaldemo.cc b/examples/cxx-api/evaldemo.cc
index e5cc8d8e..34373487 100644
--- a/examples/cxx-api/evaldemo.cc
+++ b/examples/cxx-api/evaldemo.cc
@@ -22,7 +22,7 @@ struct EvalDemoPass : public Pass
{
EvalDemoPass() : Pass("evaldemo") { }
- virtual void execute(vector<string>, Design *design)
+ void execute(vector<string>, Design *design) YS_OVERRIDE
{
Module *module = design->top_module();
diff --git a/examples/gowin/.gitignore b/examples/gowin/.gitignore
new file mode 100644
index 00000000..71030bdb
--- /dev/null
+++ b/examples/gowin/.gitignore
@@ -0,0 +1,8 @@
+demo.bit
+demo.out
+demo.rpt
+demo_syn.v
+demo_out.v
+demo_tr.html
+testbench
+testbench.vcd
diff --git a/examples/gowin/README b/examples/gowin/README
new file mode 100644
index 00000000..0194e9f0
--- /dev/null
+++ b/examples/gowin/README
@@ -0,0 +1,17 @@
+Simple test project for Gowinsemi GW2A-55K Eval Board Mini.
+
+Follow the install instructions for the Gowinsemi tools below,
+then run "bash run.sh" in this directory.
+
+
+Install instructions for gowinTool_linux
+----------------------------------------
+
+1.) extract gowinTool_linux.zip
+
+2.) set GOWIN_HOME env variable to the full path to the
+gowinTool_linux directory
+
+3.) edit gowinTool_linux/bin/gwlicense.ini. Set lic="..." to
+the full path to the license file.
+
diff --git a/examples/gowin/demo.cst b/examples/gowin/demo.cst
new file mode 100644
index 00000000..22d7eb66
--- /dev/null
+++ b/examples/gowin/demo.cst
@@ -0,0 +1,41 @@
+// 50 MHz Clock
+IO_LOC "clk" D11;
+
+// LEDs
+IO_LOC "leds[0]" D22;
+IO_LOC "leds[1]" E22;
+IO_LOC "leds[2]" G22;
+IO_LOC "leds[3]" J22;
+IO_LOC "leds[4]" L22;
+IO_LOC "leds[5]" L19;
+IO_LOC "leds[6]" L20;
+IO_LOC "leds[7]" M21;
+IO_LOC "leds[8]" N19;
+IO_LOC "leds[9]" R19;
+IO_LOC "leds[10]" T18;
+IO_LOC "leds[11]" AA22;
+IO_LOC "leds[12]" U18;
+IO_LOC "leds[13]" V20;
+IO_LOC "leds[14]" AA21;
+IO_LOC "leds[15]" AB21;
+
+
+// 7-Segment Display
+IO_LOC "seg7dig[0]" E20;
+IO_LOC "seg7dig[1]" G18;
+IO_LOC "seg7dig[2]" G20;
+IO_LOC "seg7dig[3]" F21;
+IO_LOC "seg7dig[4]" J20;
+IO_LOC "seg7dig[5]" H21;
+IO_LOC "seg7dig[6]" H18;
+IO_LOC "seg7dig[7]" D20;
+IO_LOC "seg7sel[0]" C19;
+IO_LOC "seg7sel[1]" B22;
+IO_LOC "seg7sel[2]" C20;
+IO_LOC "seg7sel[3]" C21;
+
+// Switches
+IO_LOC "sw[0]" AB20;
+IO_LOC "sw[1]" AB19;
+IO_LOC "sw[2]" AB18;
+IO_LOC "sw[3]" AB17;
diff --git a/examples/gowin/demo.sdc b/examples/gowin/demo.sdc
new file mode 100644
index 00000000..6c90325f
--- /dev/null
+++ b/examples/gowin/demo.sdc
@@ -0,0 +1 @@
+create_clock -name clk -period 20 -waveform {0 10} [get_ports {clk}]
diff --git a/examples/gowin/demo.v b/examples/gowin/demo.v
new file mode 100644
index 00000000..6ea10838
--- /dev/null
+++ b/examples/gowin/demo.v
@@ -0,0 +1,12 @@
+module demo (
+ input clk,
+ input [3:0] sw,
+ output [15:0] leds,
+ output [7:0] seg7dig,
+ output [3:0] seg7sel
+);
+ localparam PRESCALE = 20;
+ reg [PRESCALE+3:0] counter = 0;
+ always @(posedge clk) counter <= counter + 1;
+ assign leds = 1 << counter[PRESCALE +: 4];
+endmodule
diff --git a/examples/gowin/run.sh b/examples/gowin/run.sh
new file mode 100644
index 00000000..33a7b5c3
--- /dev/null
+++ b/examples/gowin/run.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+set -ex
+yosys -p "synth_gowin -top demo -vout demo_syn.v" demo.v
+$GOWIN_HOME/bin/gowin -d demo_syn.v -cst demo.cst -sdc demo.sdc -p GW2A55-PBGA484-6 \
+ -warning_all -out demo_out.v -rpt demo.rpt -tr demo_tr.html -bit demo.bit
+
+# post place&route simulation (icarus verilog)
+if false; then
+ iverilog -D POST_IMPL -o testbench -s testbench testbench.v \
+ demo_out.v $(yosys-config --datdir/gowin/cells_sim.v)
+ vvp -N testbench
+fi
diff --git a/examples/gowin/testbench.v b/examples/gowin/testbench.v
new file mode 100644
index 00000000..6d206381
--- /dev/null
+++ b/examples/gowin/testbench.v
@@ -0,0 +1,40 @@
+module testbench;
+ reg clk;
+
+ initial begin
+ #5 clk = 0;
+ forever #5 clk = ~clk;
+ end
+
+ wire [15:0] leds;
+
+ initial begin
+ // $dumpfile("testbench.vcd");
+ // $dumpvars(0, testbench);
+ $monitor("%b", leds);
+ end
+
+ demo uut (
+ .clk (clk ),
+`ifdef POST_IMPL
+ .\leds[0] (leds[0]),
+ .\leds[1] (leds[1]),
+ .\leds[2] (leds[2]),
+ .\leds[3] (leds[3]),
+ .\leds[4] (leds[4]),
+ .\leds[5] (leds[5]),
+ .\leds[6] (leds[6]),
+ .\leds[7] (leds[7]),
+ .\leds[8] (leds[8]),
+ .\leds[9] (leds[9]),
+ .\leds[10] (leds[10]),
+ .\leds[11] (leds[11]),
+ .\leds[12] (leds[12]),
+ .\leds[13] (leds[13]),
+ .\leds[14] (leds[14]),
+ .\leds[15] (leds[15])
+`else
+ .leds(leds)
+`endif
+ );
+endmodule
diff --git a/examples/intel/DE2i-150/quartus_compile/de2i.qpf b/examples/intel/DE2i-150/quartus_compile/de2i.qpf
new file mode 100644
index 00000000..9fc734eb
--- /dev/null
+++ b/examples/intel/DE2i-150/quartus_compile/de2i.qpf
@@ -0,0 +1,4 @@
+QUARTUS_VERSION = "16.1"
+# Revisions
+
+PROJECT_REVISION = "de2i"
diff --git a/examples/intel/DE2i-150/quartus_compile/de2i.qsf b/examples/intel/DE2i-150/quartus_compile/de2i.qsf
new file mode 100644
index 00000000..5a230155
--- /dev/null
+++ b/examples/intel/DE2i-150/quartus_compile/de2i.qsf
@@ -0,0 +1,1099 @@
+set_global_assignment -name FAMILY "Cyclone IV GX"
+set_global_assignment -name DEVICE EP4CGX150DF31C7
+set_global_assignment -name TOP_LEVEL_ENTITY "top"
+set_global_assignment -name DEVICE_FILTER_PACKAGE FBGA
+
+
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to CLOCK2_50
+set_instance_assignment -name IO_STANDARD "2.5 V" -to CLOCK3_50
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to CLOCK_50
+
+#============================================================
+# DRAM
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[0]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[2]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[3]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[4]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[5]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[6]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[7]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[8]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[9]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[10]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[11]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_ADDR[12]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_BA[0]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_BA[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CAS_N
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CKE
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CLK
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_CS_N
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[0]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[2]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[3]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[4]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[5]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[6]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[7]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[8]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[9]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[10]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[11]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[12]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[13]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[14]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[15]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[16]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[17]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[18]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[19]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[20]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[21]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[22]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[23]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[24]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[25]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[26]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[27]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[28]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[29]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[30]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQ[31]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQM[0]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQM[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQM[2]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_DQM[3]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_RAS_N
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to DRAM_WE_N
+
+#============================================================
+# EEP
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to EEP_I2C_SCLK
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to EEP_I2C_SDAT
+
+#============================================================
+# ENET
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_GTX_CLK
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_INT_N
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_LINK100
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_MDC
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_MDIO
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_RST_N
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_RX_CLK
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_RX_COL
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_RX_CRS
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_RX_DATA[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_RX_DATA[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_RX_DATA[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_RX_DATA[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_RX_DV
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_RX_ER
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_TX_CLK
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_TX_DATA[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_TX_DATA[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_TX_DATA[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_TX_DATA[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_TX_EN
+set_instance_assignment -name IO_STANDARD "2.5 V" -to ENET_TX_ER
+
+#============================================================
+# FAN
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to FAN_CTRL
+
+#============================================================
+# FLASH
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FL_RESET_N
+
+#============================================================
+# FS
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[2]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[3]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[4]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[5]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[6]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[7]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[8]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[9]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[10]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[11]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[12]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[13]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[14]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[15]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[16]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[17]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[18]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[19]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[20]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[21]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[22]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[23]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[24]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[25]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_ADDR[26]
+
+#============================================================
+# FL
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FL_CE_N
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FL_OE_N
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FL_RY
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FL_WE_N
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FL_WP_N
+
+#============================================================
+# FS
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[0]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[2]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[3]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[4]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[5]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[6]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[7]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[8]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[9]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[10]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[11]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[12]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[13]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[14]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[15]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[16]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[17]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[18]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[19]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[20]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[21]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[22]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[23]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[24]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[25]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[26]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[27]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[28]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[29]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[30]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FS_DQ[31]
+
+#============================================================
+# GPIO
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[0]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[2]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[3]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[4]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[5]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[6]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[7]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[8]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[9]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[10]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[11]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[12]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[13]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[14]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[15]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[16]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[17]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[18]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[19]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[20]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[21]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[22]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[23]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[24]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[25]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[26]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[27]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[28]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[29]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[30]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[31]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[32]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[33]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[34]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to GPIO[35]
+
+#============================================================
+# G
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to G_SENSOR_INT1
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to G_SENSOR_SCLK
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to G_SENSOR_SDAT
+
+#============================================================
+# HEX0
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX0[6]
+
+#============================================================
+# HEX1
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX1[6]
+
+#============================================================
+# HEX2
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX2[6]
+
+#============================================================
+# HEX3
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX3[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX3[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX3[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX3[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX3[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX3[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX3[6]
+
+#============================================================
+# HEX4
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX4[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX4[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX4[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX4[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX4[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX4[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX4[6]
+
+#============================================================
+# HEX5
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX5[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX5[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX5[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX5[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX5[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX5[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX5[6]
+
+#============================================================
+# HEX6
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX6[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX6[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX6[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX6[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX6[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX6[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX6[6]
+
+#============================================================
+# HEX7
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX7[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX7[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX7[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX7[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX7[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX7[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HEX7[6]
+
+#============================================================
+# HSMC
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_CLKIN0
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_CLKIN_N1
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_CLKIN_N2
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_CLKIN_P1
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_CLKIN_P2
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_CLKOUT0
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_CLKOUT_N1
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_CLKOUT_N2
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_CLKOUT_P1
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_CLKOUT_P2
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_D[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_D[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_D[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_D[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_I2C_SCLK
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_I2C_SDAT
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[6]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[7]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[8]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[9]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[10]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[11]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[12]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[13]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[14]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[15]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_N[16]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[6]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[7]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[8]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[9]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[10]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[11]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[12]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[13]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[14]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[15]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_RX_D_P[16]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[6]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[7]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[8]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[9]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[10]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[11]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[12]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[13]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[14]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[15]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_N[16]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[6]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[7]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[8]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[9]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[10]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[11]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[12]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[13]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[14]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[15]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to HSMC_TX_D_P[16]
+
+#============================================================
+# I2C
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to I2C_SCLK
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to I2C_SDAT
+
+#============================================================
+# IRDA
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to IRDA_RXD
+
+#============================================================
+# KEY
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to KEY[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to KEY[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to KEY[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to KEY[3]
+
+#============================================================
+# LCD
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LCD_DATA[0]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LCD_DATA[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LCD_DATA[2]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LCD_DATA[3]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LCD_DATA[4]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LCD_DATA[5]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LCD_DATA[6]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LCD_DATA[7]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LCD_EN
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LCD_ON
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LCD_RS
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LCD_RW
+
+#============================================================
+# LEDG
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[6]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[7]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDG[8]
+
+#============================================================
+# LEDR
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[6]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[7]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[8]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[9]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[10]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[11]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[12]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[13]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[14]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[15]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[16]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to LEDR[17]
+
+#============================================================
+# PCIE
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to PCIE_PERST_N
+set_instance_assignment -name IO_STANDARD HCSL -to PCIE_REFCLK_P
+set_instance_assignment -name IO_STANDARD "1.5-V PCML" -to PCIE_RX_P[0]
+set_instance_assignment -name IO_STANDARD "1.5-V PCML" -to PCIE_RX_P[1]
+set_instance_assignment -name IO_STANDARD "1.5-V PCML" -to PCIE_TX_P[0]
+set_instance_assignment -name IO_STANDARD "1.5-V PCML" -to PCIE_TX_P[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to PCIE_WAKE_N
+
+#============================================================
+# SD
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SD_CLK
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SD_CMD
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SD_DAT[0]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SD_DAT[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SD_DAT[2]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SD_DAT[3]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SD_WP_N
+
+#============================================================
+# SMA
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SMA_CLKIN
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SMA_CLKOUT
+
+#============================================================
+# SSRAM0
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SSRAM0_CE_N
+
+#============================================================
+# SSRAM1
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SSRAM1_CE_N
+
+#============================================================
+# SSRAM
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SSRAM_ADSC_N
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SSRAM_ADSP_N
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SSRAM_ADV_N
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SSRAM_BE[0]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SSRAM_BE[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SSRAM_BE[2]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SSRAM_BE[3]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SSRAM_CLK
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SSRAM_GW_N
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SSRAM_OE_N
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SSRAM_WE_N
+
+#============================================================
+# SW
+#============================================================
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[0]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[1]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[2]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[3]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[4]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[5]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[6]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[7]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[8]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[9]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[10]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[11]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[12]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[13]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[14]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[15]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[16]
+set_instance_assignment -name IO_STANDARD "2.5 V" -to SW[17]
+
+#============================================================
+# TD
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to TD_CLK27
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to TD_DATA[0]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to TD_DATA[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to TD_DATA[2]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to TD_DATA[3]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to TD_DATA[4]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to TD_DATA[5]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to TD_DATA[6]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to TD_DATA[7]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to TD_HS
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to TD_RESET_N
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to TD_VS
+
+#============================================================
+# UART
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to UART_CTS
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to UART_RTS
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to UART_RXD
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to UART_TXD
+
+#============================================================
+# VGA
+#============================================================
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[0]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[2]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[3]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[4]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[5]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[6]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_B[7]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_BLANK_N
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_CLK
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[0]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[2]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[3]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[4]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[5]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[6]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_G[7]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_HS
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[0]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[1]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[2]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[3]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[4]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[5]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[6]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_R[7]
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_SYNC_N
+set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_VS
+
+#============================================================
+# End of pin assignments by Terasic System Builder
+#============================================================
+
+
+
+set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
+set_location_assignment PIN_A15 -to CLOCK2_50
+set_location_assignment PIN_V11 -to CLOCK3_50
+set_location_assignment PIN_AJ16 -to CLOCK_50
+set_location_assignment PIN_AG7 -to DRAM_ADDR[0]
+set_location_assignment PIN_AJ7 -to DRAM_ADDR[1]
+set_location_assignment PIN_AG8 -to DRAM_ADDR[2]
+set_location_assignment PIN_AH8 -to DRAM_ADDR[3]
+set_location_assignment PIN_AE16 -to DRAM_ADDR[4]
+set_location_assignment PIN_AF16 -to DRAM_ADDR[5]
+set_location_assignment PIN_AE14 -to DRAM_ADDR[6]
+set_location_assignment PIN_AE15 -to DRAM_ADDR[7]
+set_location_assignment PIN_AE13 -to DRAM_ADDR[8]
+set_location_assignment PIN_AE12 -to DRAM_ADDR[9]
+set_location_assignment PIN_AH6 -to DRAM_ADDR[10]
+set_location_assignment PIN_AE11 -to DRAM_ADDR[11]
+set_location_assignment PIN_AE10 -to DRAM_ADDR[12]
+set_location_assignment PIN_AH5 -to DRAM_BA[0]
+set_location_assignment PIN_AG6 -to DRAM_BA[1]
+set_location_assignment PIN_AJ4 -to DRAM_CAS_N
+set_location_assignment PIN_AD6 -to DRAM_CKE
+set_location_assignment PIN_AE6 -to DRAM_CLK
+set_location_assignment PIN_AG5 -to DRAM_CS_N
+set_location_assignment PIN_AD10 -to DRAM_DQ[0]
+set_location_assignment PIN_AD9 -to DRAM_DQ[1]
+set_location_assignment PIN_AE9 -to DRAM_DQ[2]
+set_location_assignment PIN_AE8 -to DRAM_DQ[3]
+set_location_assignment PIN_AE7 -to DRAM_DQ[4]
+set_location_assignment PIN_AF7 -to DRAM_DQ[5]
+set_location_assignment PIN_AF6 -to DRAM_DQ[6]
+set_location_assignment PIN_AF9 -to DRAM_DQ[7]
+set_location_assignment PIN_AB13 -to DRAM_DQ[8]
+set_location_assignment PIN_AF13 -to DRAM_DQ[9]
+set_location_assignment PIN_AF12 -to DRAM_DQ[10]
+set_location_assignment PIN_AG9 -to DRAM_DQ[11]
+set_location_assignment PIN_AA13 -to DRAM_DQ[12]
+set_location_assignment PIN_AB11 -to DRAM_DQ[13]
+set_location_assignment PIN_AA12 -to DRAM_DQ[14]
+set_location_assignment PIN_AA15 -to DRAM_DQ[15]
+set_location_assignment PIN_AH11 -to DRAM_DQ[16]
+set_location_assignment PIN_AG11 -to DRAM_DQ[17]
+set_location_assignment PIN_AH12 -to DRAM_DQ[18]
+set_location_assignment PIN_AG12 -to DRAM_DQ[19]
+set_location_assignment PIN_AH13 -to DRAM_DQ[20]
+set_location_assignment PIN_AG13 -to DRAM_DQ[21]
+set_location_assignment PIN_AG14 -to DRAM_DQ[22]
+set_location_assignment PIN_AH14 -to DRAM_DQ[23]
+set_location_assignment PIN_AH9 -to DRAM_DQ[24]
+set_location_assignment PIN_AK8 -to DRAM_DQ[25]
+set_location_assignment PIN_AG10 -to DRAM_DQ[26]
+set_location_assignment PIN_AK7 -to DRAM_DQ[27]
+set_location_assignment PIN_AH7 -to DRAM_DQ[28]
+set_location_assignment PIN_AK6 -to DRAM_DQ[29]
+set_location_assignment PIN_AJ6 -to DRAM_DQ[30]
+set_location_assignment PIN_AK5 -to DRAM_DQ[31]
+set_location_assignment PIN_AF10 -to DRAM_DQM[0]
+set_location_assignment PIN_AB14 -to DRAM_DQM[1]
+set_location_assignment PIN_AH15 -to DRAM_DQM[2]
+set_location_assignment PIN_AH10 -to DRAM_DQM[3]
+set_location_assignment PIN_AK4 -to DRAM_RAS_N
+set_location_assignment PIN_AK3 -to DRAM_WE_N
+set_location_assignment PIN_AG27 -to EEP_I2C_SCLK
+set_location_assignment PIN_AG25 -to EEP_I2C_SDAT
+set_location_assignment PIN_A12 -to ENET_GTX_CLK
+set_location_assignment PIN_E16 -to ENET_INT_N
+set_location_assignment PIN_F5 -to ENET_LINK100
+set_location_assignment PIN_C16 -to ENET_MDC
+set_location_assignment PIN_C15 -to ENET_MDIO
+set_location_assignment PIN_C14 -to ENET_RST_N
+set_location_assignment PIN_L15 -to ENET_RX_CLK
+set_location_assignment PIN_G15 -to ENET_RX_COL
+set_location_assignment PIN_D6 -to ENET_RX_CRS
+set_location_assignment PIN_F15 -to ENET_RX_DATA[0]
+set_location_assignment PIN_E13 -to ENET_RX_DATA[1]
+set_location_assignment PIN_A5 -to ENET_RX_DATA[2]
+set_location_assignment PIN_B7 -to ENET_RX_DATA[3]
+set_location_assignment PIN_A8 -to ENET_RX_DV
+set_location_assignment PIN_D11 -to ENET_RX_ER
+set_location_assignment PIN_F13 -to ENET_TX_CLK
+set_location_assignment PIN_B12 -to ENET_TX_DATA[0]
+set_location_assignment PIN_E7 -to ENET_TX_DATA[1]
+set_location_assignment PIN_C13 -to ENET_TX_DATA[2]
+set_location_assignment PIN_D15 -to ENET_TX_DATA[3]
+set_location_assignment PIN_D14 -to ENET_TX_EN
+set_location_assignment PIN_D13 -to ENET_TX_ER
+set_location_assignment PIN_AF28 -to FAN_CTRL
+set_location_assignment PIN_AG18 -to FL_RESET_N
+set_location_assignment PIN_AB22 -to FS_ADDR[1]
+set_location_assignment PIN_AH19 -to FS_ADDR[2]
+set_location_assignment PIN_AK19 -to FS_ADDR[3]
+set_location_assignment PIN_AJ18 -to FS_ADDR[4]
+set_location_assignment PIN_AA18 -to FS_ADDR[5]
+set_location_assignment PIN_AH18 -to FS_ADDR[6]
+set_location_assignment PIN_AK17 -to FS_ADDR[7]
+set_location_assignment PIN_Y20 -to FS_ADDR[8]
+set_location_assignment PIN_AK21 -to FS_ADDR[9]
+set_location_assignment PIN_AH21 -to FS_ADDR[10]
+set_location_assignment PIN_AG21 -to FS_ADDR[11]
+set_location_assignment PIN_AG22 -to FS_ADDR[12]
+set_location_assignment PIN_AD22 -to FS_ADDR[13]
+set_location_assignment PIN_AE24 -to FS_ADDR[14]
+set_location_assignment PIN_AD23 -to FS_ADDR[15]
+set_location_assignment PIN_AB21 -to FS_ADDR[16]
+set_location_assignment PIN_AH17 -to FS_ADDR[17]
+set_location_assignment PIN_AE17 -to FS_ADDR[18]
+set_location_assignment PIN_AG20 -to FS_ADDR[19]
+set_location_assignment PIN_AK20 -to FS_ADDR[20]
+set_location_assignment PIN_AE19 -to FS_ADDR[21]
+set_location_assignment PIN_AA16 -to FS_ADDR[22]
+set_location_assignment PIN_AF15 -to FS_ADDR[23]
+set_location_assignment PIN_AG15 -to FS_ADDR[24]
+set_location_assignment PIN_Y17 -to FS_ADDR[25]
+set_location_assignment PIN_AB16 -to FS_ADDR[26]
+set_location_assignment PIN_AG19 -to FL_CE_N
+set_location_assignment PIN_AJ19 -to FL_OE_N
+set_location_assignment PIN_AF19 -to FL_RY
+set_location_assignment PIN_AG17 -to FL_WE_N
+set_location_assignment PIN_AK18 -to FL_WP_N
+set_location_assignment PIN_AK29 -to FS_DQ[0]
+set_location_assignment PIN_AE23 -to FS_DQ[1]
+set_location_assignment PIN_AH24 -to FS_DQ[2]
+set_location_assignment PIN_AH23 -to FS_DQ[3]
+set_location_assignment PIN_AA21 -to FS_DQ[4]
+set_location_assignment PIN_AE20 -to FS_DQ[5]
+set_location_assignment PIN_Y19 -to FS_DQ[6]
+set_location_assignment PIN_AA17 -to FS_DQ[7]
+set_location_assignment PIN_AB17 -to FS_DQ[8]
+set_location_assignment PIN_Y18 -to FS_DQ[9]
+set_location_assignment PIN_AA20 -to FS_DQ[10]
+set_location_assignment PIN_AE21 -to FS_DQ[11]
+set_location_assignment PIN_AH22 -to FS_DQ[12]
+set_location_assignment PIN_AJ24 -to FS_DQ[13]
+set_location_assignment PIN_AE22 -to FS_DQ[14]
+set_location_assignment PIN_AK28 -to FS_DQ[15]
+set_location_assignment PIN_AK9 -to FS_DQ[16]
+set_location_assignment PIN_AJ10 -to FS_DQ[17]
+set_location_assignment PIN_AK11 -to FS_DQ[18]
+set_location_assignment PIN_AK12 -to FS_DQ[19]
+set_location_assignment PIN_AJ13 -to FS_DQ[20]
+set_location_assignment PIN_AK15 -to FS_DQ[21]
+set_location_assignment PIN_AC16 -to FS_DQ[22]
+set_location_assignment PIN_AH16 -to FS_DQ[23]
+set_location_assignment PIN_AG16 -to FS_DQ[24]
+set_location_assignment PIN_AD16 -to FS_DQ[25]
+set_location_assignment PIN_AJ15 -to FS_DQ[26]
+set_location_assignment PIN_AK14 -to FS_DQ[27]
+set_location_assignment PIN_AK13 -to FS_DQ[28]
+set_location_assignment PIN_AJ12 -to FS_DQ[29]
+set_location_assignment PIN_AK10 -to FS_DQ[30]
+set_location_assignment PIN_AJ9 -to FS_DQ[31]
+set_location_assignment PIN_G16 -to GPIO[0]
+set_location_assignment PIN_F17 -to GPIO[1]
+set_location_assignment PIN_D18 -to GPIO[2]
+set_location_assignment PIN_F18 -to GPIO[3]
+set_location_assignment PIN_D19 -to GPIO[4]
+set_location_assignment PIN_K21 -to GPIO[5]
+set_location_assignment PIN_F19 -to GPIO[6]
+set_location_assignment PIN_K22 -to GPIO[7]
+set_location_assignment PIN_B21 -to GPIO[8]
+set_location_assignment PIN_C21 -to GPIO[9]
+set_location_assignment PIN_D22 -to GPIO[10]
+set_location_assignment PIN_D21 -to GPIO[11]
+set_location_assignment PIN_D23 -to GPIO[12]
+set_location_assignment PIN_D24 -to GPIO[13]
+set_location_assignment PIN_B28 -to GPIO[14]
+set_location_assignment PIN_C25 -to GPIO[15]
+set_location_assignment PIN_C26 -to GPIO[16]
+set_location_assignment PIN_D28 -to GPIO[17]
+set_location_assignment PIN_D25 -to GPIO[18]
+set_location_assignment PIN_F20 -to GPIO[19]
+set_location_assignment PIN_E21 -to GPIO[20]
+set_location_assignment PIN_F23 -to GPIO[21]
+set_location_assignment PIN_G20 -to GPIO[22]
+set_location_assignment PIN_F22 -to GPIO[23]
+set_location_assignment PIN_G22 -to GPIO[24]
+set_location_assignment PIN_G24 -to GPIO[25]
+set_location_assignment PIN_G23 -to GPIO[26]
+set_location_assignment PIN_A25 -to GPIO[27]
+set_location_assignment PIN_A26 -to GPIO[28]
+set_location_assignment PIN_A19 -to GPIO[29]
+set_location_assignment PIN_A28 -to GPIO[30]
+set_location_assignment PIN_A27 -to GPIO[31]
+set_location_assignment PIN_B30 -to GPIO[32]
+set_location_assignment PIN_AG28 -to GPIO[33]
+set_location_assignment PIN_AG26 -to GPIO[34]
+set_location_assignment PIN_Y21 -to GPIO[35]
+set_location_assignment PIN_AC30 -to G_SENSOR_INT1
+set_location_assignment PIN_AK27 -to G_SENSOR_SCLK
+set_location_assignment PIN_AK26 -to G_SENSOR_SDAT
+set_location_assignment PIN_E15 -to HEX0[0]
+set_location_assignment PIN_E12 -to HEX0[1]
+set_location_assignment PIN_G11 -to HEX0[2]
+set_location_assignment PIN_F11 -to HEX0[3]
+set_location_assignment PIN_F16 -to HEX0[4]
+set_location_assignment PIN_D16 -to HEX0[5]
+set_location_assignment PIN_F14 -to HEX0[6]
+set_location_assignment PIN_G14 -to HEX1[0]
+set_location_assignment PIN_B13 -to HEX1[1]
+set_location_assignment PIN_G13 -to HEX1[2]
+set_location_assignment PIN_F12 -to HEX1[3]
+set_location_assignment PIN_G12 -to HEX1[4]
+set_location_assignment PIN_J9 -to HEX1[5]
+set_location_assignment PIN_G10 -to HEX1[6]
+set_location_assignment PIN_G8 -to HEX2[0]
+set_location_assignment PIN_G7 -to HEX2[1]
+set_location_assignment PIN_F7 -to HEX2[2]
+set_location_assignment PIN_AG30 -to HEX2[3]
+set_location_assignment PIN_F6 -to HEX2[4]
+set_location_assignment PIN_F4 -to HEX2[5]
+set_location_assignment PIN_F10 -to HEX2[6]
+set_location_assignment PIN_D10 -to HEX3[0]
+set_location_assignment PIN_D7 -to HEX3[1]
+set_location_assignment PIN_E6 -to HEX3[2]
+set_location_assignment PIN_E4 -to HEX3[3]
+set_location_assignment PIN_E3 -to HEX3[4]
+set_location_assignment PIN_D5 -to HEX3[5]
+set_location_assignment PIN_D4 -to HEX3[6]
+set_location_assignment PIN_A14 -to HEX4[0]
+set_location_assignment PIN_A13 -to HEX4[1]
+set_location_assignment PIN_C7 -to HEX4[2]
+set_location_assignment PIN_C6 -to HEX4[3]
+set_location_assignment PIN_C5 -to HEX4[4]
+set_location_assignment PIN_C4 -to HEX4[5]
+set_location_assignment PIN_C3 -to HEX4[6]
+set_location_assignment PIN_D3 -to HEX5[0]
+set_location_assignment PIN_A10 -to HEX5[1]
+set_location_assignment PIN_A9 -to HEX5[2]
+set_location_assignment PIN_A7 -to HEX5[3]
+set_location_assignment PIN_A6 -to HEX5[4]
+set_location_assignment PIN_A11 -to HEX5[5]
+set_location_assignment PIN_B6 -to HEX5[6]
+set_location_assignment PIN_B9 -to HEX6[0]
+set_location_assignment PIN_B10 -to HEX6[1]
+set_location_assignment PIN_C8 -to HEX6[2]
+set_location_assignment PIN_C9 -to HEX6[3]
+set_location_assignment PIN_D8 -to HEX6[4]
+set_location_assignment PIN_D9 -to HEX6[5]
+set_location_assignment PIN_E9 -to HEX6[6]
+set_location_assignment PIN_E10 -to HEX7[0]
+set_location_assignment PIN_F8 -to HEX7[1]
+set_location_assignment PIN_F9 -to HEX7[2]
+set_location_assignment PIN_C10 -to HEX7[3]
+set_location_assignment PIN_C11 -to HEX7[4]
+set_location_assignment PIN_C12 -to HEX7[5]
+set_location_assignment PIN_D12 -to HEX7[6]
+set_location_assignment PIN_K15 -to HSMC_CLKIN0
+set_location_assignment PIN_V30 -to HSMC_CLKIN_N1
+set_location_assignment PIN_T30 -to HSMC_CLKIN_N2
+set_location_assignment PIN_V29 -to HSMC_CLKIN_P1
+set_location_assignment PIN_T29 -to HSMC_CLKIN_P2
+set_location_assignment PIN_G6 -to HSMC_CLKOUT0
+set_location_assignment PIN_AB28 -to HSMC_CLKOUT_N1
+set_location_assignment PIN_Y28 -to HSMC_CLKOUT_N2
+set_location_assignment PIN_AB27 -to HSMC_CLKOUT_P1
+set_location_assignment PIN_AA28 -to HSMC_CLKOUT_P2
+set_location_assignment PIN_AC25 -to HSMC_D[0]
+set_location_assignment PIN_E27 -to HSMC_D[1]
+set_location_assignment PIN_AB26 -to HSMC_D[2]
+set_location_assignment PIN_E28 -to HSMC_D[3]
+set_location_assignment PIN_AD26 -to HSMC_I2C_SCLK
+set_location_assignment PIN_AD25 -to HSMC_I2C_SDAT
+set_location_assignment PIN_G27 -to HSMC_RX_D_N[0]
+set_location_assignment PIN_G29 -to HSMC_RX_D_N[1]
+set_location_assignment PIN_H27 -to HSMC_RX_D_N[2]
+set_location_assignment PIN_K29 -to HSMC_RX_D_N[3]
+set_location_assignment PIN_L28 -to HSMC_RX_D_N[4]
+set_location_assignment PIN_M28 -to HSMC_RX_D_N[5]
+set_location_assignment PIN_N30 -to HSMC_RX_D_N[6]
+set_location_assignment PIN_P28 -to HSMC_RX_D_N[7]
+set_location_assignment PIN_R28 -to HSMC_RX_D_N[8]
+set_location_assignment PIN_U28 -to HSMC_RX_D_N[9]
+set_location_assignment PIN_W28 -to HSMC_RX_D_N[10]
+set_location_assignment PIN_W30 -to HSMC_RX_D_N[11]
+set_location_assignment PIN_M30 -to HSMC_RX_D_N[12]
+set_location_assignment PIN_Y27 -to HSMC_RX_D_N[13]
+set_location_assignment PIN_AA29 -to HSMC_RX_D_N[14]
+set_location_assignment PIN_AD28 -to HSMC_RX_D_N[15]
+set_location_assignment PIN_AE28 -to HSMC_RX_D_N[16]
+set_location_assignment PIN_G26 -to HSMC_RX_D_P[0]
+set_location_assignment PIN_G28 -to HSMC_RX_D_P[1]
+set_location_assignment PIN_J27 -to HSMC_RX_D_P[2]
+set_location_assignment PIN_K28 -to HSMC_RX_D_P[3]
+set_location_assignment PIN_L27 -to HSMC_RX_D_P[4]
+set_location_assignment PIN_M27 -to HSMC_RX_D_P[5]
+set_location_assignment PIN_N29 -to HSMC_RX_D_P[6]
+set_location_assignment PIN_P27 -to HSMC_RX_D_P[7]
+set_location_assignment PIN_R27 -to HSMC_RX_D_P[8]
+set_location_assignment PIN_U27 -to HSMC_RX_D_P[9]
+set_location_assignment PIN_W27 -to HSMC_RX_D_P[10]
+set_location_assignment PIN_W29 -to HSMC_RX_D_P[11]
+set_location_assignment PIN_M29 -to HSMC_RX_D_P[12]
+set_location_assignment PIN_AA27 -to HSMC_RX_D_P[13]
+set_location_assignment PIN_AB29 -to HSMC_RX_D_P[14]
+set_location_assignment PIN_AD27 -to HSMC_RX_D_P[15]
+set_location_assignment PIN_AE27 -to HSMC_RX_D_P[16]
+set_location_assignment PIN_H28 -to HSMC_TX_D_N[0]
+set_location_assignment PIN_F29 -to HSMC_TX_D_N[1]
+set_location_assignment PIN_D30 -to HSMC_TX_D_N[2]
+set_location_assignment PIN_E30 -to HSMC_TX_D_N[3]
+set_location_assignment PIN_G30 -to HSMC_TX_D_N[4]
+set_location_assignment PIN_J30 -to HSMC_TX_D_N[5]
+set_location_assignment PIN_K27 -to HSMC_TX_D_N[6]
+set_location_assignment PIN_K30 -to HSMC_TX_D_N[7]
+set_location_assignment PIN_T25 -to HSMC_TX_D_N[8]
+set_location_assignment PIN_N28 -to HSMC_TX_D_N[9]
+set_location_assignment PIN_V26 -to HSMC_TX_D_N[10]
+set_location_assignment PIN_Y30 -to HSMC_TX_D_N[11]
+set_location_assignment PIN_AC28 -to HSMC_TX_D_N[12]
+set_location_assignment PIN_AD30 -to HSMC_TX_D_N[13]
+set_location_assignment PIN_AE30 -to HSMC_TX_D_N[14]
+set_location_assignment PIN_AH30 -to HSMC_TX_D_N[15]
+set_location_assignment PIN_AG29 -to HSMC_TX_D_N[16]
+set_location_assignment PIN_J28 -to HSMC_TX_D_P[0]
+set_location_assignment PIN_F28 -to HSMC_TX_D_P[1]
+set_location_assignment PIN_D29 -to HSMC_TX_D_P[2]
+set_location_assignment PIN_F30 -to HSMC_TX_D_P[3]
+set_location_assignment PIN_H30 -to HSMC_TX_D_P[4]
+set_location_assignment PIN_J29 -to HSMC_TX_D_P[5]
+set_location_assignment PIN_K26 -to HSMC_TX_D_P[6]
+set_location_assignment PIN_L30 -to HSMC_TX_D_P[7]
+set_location_assignment PIN_U25 -to HSMC_TX_D_P[8]
+set_location_assignment PIN_N27 -to HSMC_TX_D_P[9]
+set_location_assignment PIN_V25 -to HSMC_TX_D_P[10]
+set_location_assignment PIN_AA30 -to HSMC_TX_D_P[11]
+set_location_assignment PIN_AC27 -to HSMC_TX_D_P[12]
+set_location_assignment PIN_AD29 -to HSMC_TX_D_P[13]
+set_location_assignment PIN_AE29 -to HSMC_TX_D_P[14]
+set_location_assignment PIN_AJ30 -to HSMC_TX_D_P[15]
+set_location_assignment PIN_AH29 -to HSMC_TX_D_P[16]
+set_location_assignment PIN_C27 -to I2C_SCLK
+set_location_assignment PIN_G21 -to I2C_SDAT
+set_location_assignment PIN_AH28 -to IRDA_RXD
+set_location_assignment PIN_AA26 -to KEY[0]
+set_location_assignment PIN_AE25 -to KEY[1]
+set_location_assignment PIN_AF30 -to KEY[2]
+set_location_assignment PIN_AE26 -to KEY[3]
+set_location_assignment PIN_AG4 -to LCD_DATA[0]
+set_location_assignment PIN_AF3 -to LCD_DATA[1]
+set_location_assignment PIN_AH3 -to LCD_DATA[2]
+set_location_assignment PIN_AE5 -to LCD_DATA[3]
+set_location_assignment PIN_AH2 -to LCD_DATA[4]
+set_location_assignment PIN_AE3 -to LCD_DATA[5]
+set_location_assignment PIN_AH4 -to LCD_DATA[6]
+set_location_assignment PIN_AE4 -to LCD_DATA[7]
+set_location_assignment PIN_AF4 -to LCD_EN
+set_location_assignment PIN_AF27 -to LCD_ON
+set_location_assignment PIN_AG3 -to LCD_RS
+set_location_assignment PIN_AJ3 -to LCD_RW
+set_location_assignment PIN_AA25 -to LEDG[0]
+set_location_assignment PIN_AB25 -to LEDG[1]
+set_location_assignment PIN_F27 -to LEDG[2]
+set_location_assignment PIN_F26 -to LEDG[3]
+set_location_assignment PIN_W26 -to LEDG[4]
+set_location_assignment PIN_Y22 -to LEDG[5]
+set_location_assignment PIN_Y25 -to LEDG[6]
+set_location_assignment PIN_AA22 -to LEDG[7]
+set_location_assignment PIN_J25 -to LEDG[8]
+set_location_assignment PIN_T23 -to LEDR[0]
+set_location_assignment PIN_T24 -to LEDR[1]
+set_location_assignment PIN_V27 -to LEDR[2]
+set_location_assignment PIN_W25 -to LEDR[3]
+set_location_assignment PIN_T21 -to LEDR[4]
+set_location_assignment PIN_T26 -to LEDR[5]
+set_location_assignment PIN_R25 -to LEDR[6]
+set_location_assignment PIN_T27 -to LEDR[7]
+set_location_assignment PIN_P25 -to LEDR[8]
+set_location_assignment PIN_R24 -to LEDR[9]
+set_location_assignment PIN_P21 -to LEDR[10]
+set_location_assignment PIN_N24 -to LEDR[11]
+set_location_assignment PIN_N21 -to LEDR[12]
+set_location_assignment PIN_M25 -to LEDR[13]
+set_location_assignment PIN_K24 -to LEDR[14]
+set_location_assignment PIN_L25 -to LEDR[15]
+set_location_assignment PIN_M21 -to LEDR[16]
+set_location_assignment PIN_M22 -to LEDR[17]
+set_location_assignment PIN_A4 -to PCIE_PERST_N
+set_location_assignment PIN_V15 -to PCIE_REFCLK_P
+set_location_assignment PIN_AC2 -to PCIE_RX_P[0]
+set_location_assignment PIN_AA2 -to PCIE_RX_P[1]
+set_location_assignment PIN_AB4 -to PCIE_TX_P[0]
+set_location_assignment PIN_Y4 -to PCIE_TX_P[1]
+set_location_assignment PIN_C29 -to PCIE_WAKE_N
+set_location_assignment PIN_AH25 -to SD_CLK
+set_location_assignment PIN_AF18 -to SD_CMD
+set_location_assignment PIN_AH27 -to SD_DAT[0]
+set_location_assignment PIN_AJ28 -to SD_DAT[1]
+set_location_assignment PIN_AD24 -to SD_DAT[2]
+set_location_assignment PIN_AE18 -to SD_DAT[3]
+set_location_assignment PIN_AJ27 -to SD_WP_N
+set_location_assignment PIN_AK16 -to SMA_CLKIN
+set_location_assignment PIN_AF25 -to SMA_CLKOUT
+set_location_assignment PIN_AJ21 -to SSRAM0_CE_N
+set_location_assignment PIN_AG23 -to SSRAM1_CE_N
+set_location_assignment PIN_AK25 -to SSRAM_ADSC_N
+set_location_assignment PIN_AJ25 -to SSRAM_ADSP_N
+set_location_assignment PIN_AH26 -to SSRAM_ADV_N
+set_location_assignment PIN_AF22 -to SSRAM_BE[0]
+set_location_assignment PIN_AK22 -to SSRAM_BE[1]
+set_location_assignment PIN_AJ22 -to SSRAM_BE[2]
+set_location_assignment PIN_AF21 -to SSRAM_BE[3]
+set_location_assignment PIN_AF24 -to SSRAM_CLK
+set_location_assignment PIN_AK23 -to SSRAM_GW_N
+set_location_assignment PIN_AG24 -to SSRAM_OE_N
+set_location_assignment PIN_AK24 -to SSRAM_WE_N
+set_location_assignment PIN_V28 -to SW[0]
+set_location_assignment PIN_U30 -to SW[1]
+set_location_assignment PIN_V21 -to SW[2]
+set_location_assignment PIN_C2 -to SW[3]
+set_location_assignment PIN_AB30 -to SW[4]
+set_location_assignment PIN_U21 -to SW[5]
+set_location_assignment PIN_T28 -to SW[6]
+set_location_assignment PIN_R30 -to SW[7]
+set_location_assignment PIN_P30 -to SW[8]
+set_location_assignment PIN_R29 -to SW[9]
+set_location_assignment PIN_R26 -to SW[10]
+set_location_assignment PIN_N26 -to SW[11]
+set_location_assignment PIN_M26 -to SW[12]
+set_location_assignment PIN_N25 -to SW[13]
+set_location_assignment PIN_J26 -to SW[14]
+set_location_assignment PIN_K25 -to SW[15]
+set_location_assignment PIN_C30 -to SW[16]
+set_location_assignment PIN_H25 -to SW[17]
+set_location_assignment PIN_B15 -to TD_CLK27
+set_location_assignment PIN_C17 -to TD_DATA[0]
+set_location_assignment PIN_D17 -to TD_DATA[1]
+set_location_assignment PIN_A16 -to TD_DATA[2]
+set_location_assignment PIN_B16 -to TD_DATA[3]
+set_location_assignment PIN_G18 -to TD_DATA[4]
+set_location_assignment PIN_G17 -to TD_DATA[5]
+set_location_assignment PIN_K18 -to TD_DATA[6]
+set_location_assignment PIN_K17 -to TD_DATA[7]
+set_location_assignment PIN_C28 -to TD_HS
+set_location_assignment PIN_E25 -to TD_RESET_N
+set_location_assignment PIN_E22 -to TD_VS
+set_location_assignment PIN_D26 -to UART_CTS
+set_location_assignment PIN_A29 -to UART_RTS
+set_location_assignment PIN_B27 -to UART_RXD
+set_location_assignment PIN_H24 -to UART_TXD
+set_location_assignment PIN_E24 -to VGA_B[0]
+set_location_assignment PIN_C24 -to VGA_B[1]
+set_location_assignment PIN_B25 -to VGA_B[2]
+set_location_assignment PIN_C23 -to VGA_B[3]
+set_location_assignment PIN_F24 -to VGA_B[4]
+set_location_assignment PIN_A23 -to VGA_B[5]
+set_location_assignment PIN_G25 -to VGA_B[6]
+set_location_assignment PIN_C22 -to VGA_B[7]
+set_location_assignment PIN_F25 -to VGA_BLANK_N
+set_location_assignment PIN_D27 -to VGA_CLK
+set_location_assignment PIN_D20 -to VGA_G[0]
+set_location_assignment PIN_C20 -to VGA_G[1]
+set_location_assignment PIN_A20 -to VGA_G[2]
+set_location_assignment PIN_K19 -to VGA_G[3]
+set_location_assignment PIN_A21 -to VGA_G[4]
+set_location_assignment PIN_F21 -to VGA_G[5]
+set_location_assignment PIN_A22 -to VGA_G[6]
+set_location_assignment PIN_B22 -to VGA_G[7]
+set_location_assignment PIN_B24 -to VGA_HS
+set_location_assignment PIN_A17 -to VGA_R[0]
+set_location_assignment PIN_C18 -to VGA_R[1]
+set_location_assignment PIN_B18 -to VGA_R[2]
+set_location_assignment PIN_A18 -to VGA_R[3]
+set_location_assignment PIN_E18 -to VGA_R[4]
+set_location_assignment PIN_E19 -to VGA_R[5]
+set_location_assignment PIN_B19 -to VGA_R[6]
+set_location_assignment PIN_C19 -to VGA_R[7]
+set_location_assignment PIN_AH20 -to VGA_SYNC_N
+set_location_assignment PIN_A24 -to VGA_VS
+set_instance_assignment -name VIRTUAL_PIN ON -to FS_ADDR[0]
+#============================================================
+set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
+set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
+set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
+set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "2.5 V"
+set_global_assignment -name VQM_FILE ../top.vqm
+set_global_assignment -name SDC_FILE de2i_150_golden_top.sdc
+set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
+set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
+set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
+set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
+set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file
diff --git a/examples/intel/DE2i-150/quartus_compile/runme_quartus b/examples/intel/DE2i-150/quartus_compile/runme_quartus
new file mode 100644
index 00000000..83aa3b60
--- /dev/null
+++ b/examples/intel/DE2i-150/quartus_compile/runme_quartus
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+export REV="de2i"
+
+quartus_map -c $REV top && \
+ quartus_fit -c $REV top && \
+ quartus_asm -c $REV top
diff --git a/examples/intel/DE2i-150/run_cycloneiv b/examples/intel/DE2i-150/run_cycloneiv
new file mode 100644
index 00000000..518807b5
--- /dev/null
+++ b/examples/intel/DE2i-150/run_cycloneiv
@@ -0,0 +1,2 @@
+#/bin/env bash
+yosys -p "synth_intel -family cycloneiv -top top -vqm top.vqm" top.v sevenseg.v
diff --git a/examples/intel/DE2i-150/sevenseg.v b/examples/intel/DE2i-150/sevenseg.v
new file mode 100644
index 00000000..06cf7c14
--- /dev/null
+++ b/examples/intel/DE2i-150/sevenseg.v
@@ -0,0 +1,25 @@
+module sevenseg ( output reg [6:0] HEX0,
+ input [3:0] SW );
+
+ always @(*) begin
+ case(SW)
+ 4'h1: HEX0 = 7'b1111001;
+ 4'h2: HEX0 = 7'b0100100;
+ 4'h3: HEX0 = 7'b0110000;
+ 4'h4: HEX0 = 7'b0011001;
+ 4'h5: HEX0 = 7'b0010010;
+ 4'h6: HEX0 = 7'b0000010;
+ 4'h7: HEX0 = 7'b1111000;
+ 4'h8: HEX0 = 7'b0000000;
+ 4'h9: HEX0 = 7'b0011000;
+ 4'ha: HEX0 = 7'b0001000;
+ 4'hb: HEX0 = 7'b0000011;
+ 4'hc: HEX0 = 7'b1000110;
+ 4'hd: HEX0 = 7'b0100001;
+ 4'he: HEX0 = 7'b0000110;
+ 4'hf: HEX0 = 7'b0001110;
+ 4'h0: HEX0 = 7'b1000000;
+ endcase // case (SW)
+ end
+
+endmodule
diff --git a/examples/intel/DE2i-150/top.v b/examples/intel/DE2i-150/top.v
new file mode 100644
index 00000000..2bada0e2
--- /dev/null
+++ b/examples/intel/DE2i-150/top.v
@@ -0,0 +1,15 @@
+`default_nettype none
+module top ( output wire [6:0] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5, HEX6, HEX7,
+ input wire [15:0] SW );
+
+
+ sevenseg UUD0 (.HEX0(HEX0), .SW(4'h7));
+ sevenseg UUD1 (.HEX0(HEX1), .SW(4'h1));
+ sevenseg UUD2 (.HEX0(HEX2), .SW(4'h0));
+ sevenseg UUD3 (.HEX0(HEX3), .SW(4'h2));
+ sevenseg UUD4 (.HEX0(HEX4), .SW(SW[3:0]));
+ sevenseg UUD5 (.HEX0(HEX5), .SW(SW[7:4]));
+ sevenseg UUD6 (.HEX0(HEX6), .SW(SW[11:8]));
+ sevenseg UUD7 (.HEX0(HEX7), .SW(SW[15:12]));
+
+endmodule
diff --git a/examples/intel/MAX10/run_max10 b/examples/intel/MAX10/run_max10
new file mode 100644
index 00000000..0378e4fa
--- /dev/null
+++ b/examples/intel/MAX10/run_max10
@@ -0,0 +1 @@
+yosys -p "synth_intel -family max10 -top top -vqm top.vqm" top.v sevenseg.v
diff --git a/examples/intel/MAX10/runme_postsynth b/examples/intel/MAX10/runme_postsynth
new file mode 100644
index 00000000..f1621054
--- /dev/null
+++ b/examples/intel/MAX10/runme_postsynth
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+iverilog -D POST_IMPL -o verif_post -s tb_top tb_top.v top.vqm $(yosys-config --datdir/altera_intel/max10/cells_comb_max10.v)
+vvp -N verif_post
+
diff --git a/examples/intel/MAX10/sevenseg.v b/examples/intel/MAX10/sevenseg.v
new file mode 100644
index 00000000..06cf7c14
--- /dev/null
+++ b/examples/intel/MAX10/sevenseg.v
@@ -0,0 +1,25 @@
+module sevenseg ( output reg [6:0] HEX0,
+ input [3:0] SW );
+
+ always @(*) begin
+ case(SW)
+ 4'h1: HEX0 = 7'b1111001;
+ 4'h2: HEX0 = 7'b0100100;
+ 4'h3: HEX0 = 7'b0110000;
+ 4'h4: HEX0 = 7'b0011001;
+ 4'h5: HEX0 = 7'b0010010;
+ 4'h6: HEX0 = 7'b0000010;
+ 4'h7: HEX0 = 7'b1111000;
+ 4'h8: HEX0 = 7'b0000000;
+ 4'h9: HEX0 = 7'b0011000;
+ 4'ha: HEX0 = 7'b0001000;
+ 4'hb: HEX0 = 7'b0000011;
+ 4'hc: HEX0 = 7'b1000110;
+ 4'hd: HEX0 = 7'b0100001;
+ 4'he: HEX0 = 7'b0000110;
+ 4'hf: HEX0 = 7'b0001110;
+ 4'h0: HEX0 = 7'b1000000;
+ endcase // case (SW)
+ end
+
+endmodule
diff --git a/examples/intel/MAX10/top.v b/examples/intel/MAX10/top.v
new file mode 100644
index 00000000..2bada0e2
--- /dev/null
+++ b/examples/intel/MAX10/top.v
@@ -0,0 +1,15 @@
+`default_nettype none
+module top ( output wire [6:0] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5, HEX6, HEX7,
+ input wire [15:0] SW );
+
+
+ sevenseg UUD0 (.HEX0(HEX0), .SW(4'h7));
+ sevenseg UUD1 (.HEX0(HEX1), .SW(4'h1));
+ sevenseg UUD2 (.HEX0(HEX2), .SW(4'h0));
+ sevenseg UUD3 (.HEX0(HEX3), .SW(4'h2));
+ sevenseg UUD4 (.HEX0(HEX4), .SW(SW[3:0]));
+ sevenseg UUD5 (.HEX0(HEX5), .SW(SW[7:4]));
+ sevenseg UUD6 (.HEX0(HEX6), .SW(SW[11:8]));
+ sevenseg UUD7 (.HEX0(HEX7), .SW(SW[15:12]));
+
+endmodule
diff --git a/examples/intel/asicworld_lfsr/README b/examples/intel/asicworld_lfsr/README
new file mode 100644
index 00000000..ba365fab
--- /dev/null
+++ b/examples/intel/asicworld_lfsr/README
@@ -0,0 +1,6 @@
+Source of the files:
+http://www.asic-world.com/examples/verilog/lfsr.html
+
+Run first: runme_presynth
+Generate output netlist with run_max10 or run_cycloneiv
+Then, check with: runme_postsynth
diff --git a/examples/intel/asicworld_lfsr/lfsr_updown.v b/examples/intel/asicworld_lfsr/lfsr_updown.v
new file mode 100644
index 00000000..43db1606
--- /dev/null
+++ b/examples/intel/asicworld_lfsr/lfsr_updown.v
@@ -0,0 +1,35 @@
+`default_nettype none
+module lfsr_updown (
+clk , // Clock input
+reset , // Reset input
+enable , // Enable input
+up_down , // Up Down input
+count , // Count output
+overflow // Overflow output
+);
+
+ input clk;
+ input reset;
+ input enable;
+ input up_down;
+
+ output [7 : 0] count;
+ output overflow;
+
+ reg [7 : 0] count;
+
+ assign overflow = (up_down) ? (count == {{7{1'b0}}, 1'b1}) :
+ (count == {1'b1, {7{1'b0}}}) ;
+
+ always @(posedge clk)
+ if (reset)
+ count <= {7{1'b0}};
+ else if (enable) begin
+ if (up_down) begin
+ count <= {~(^(count & 8'b01100011)),count[7:1]};
+ end else begin
+ count <= {count[5:0],~(^(count & 8'b10110001))};
+ end
+ end
+
+endmodule
diff --git a/examples/intel/asicworld_lfsr/lfsr_updown_tb.v b/examples/intel/asicworld_lfsr/lfsr_updown_tb.v
new file mode 100644
index 00000000..db29e60f
--- /dev/null
+++ b/examples/intel/asicworld_lfsr/lfsr_updown_tb.v
@@ -0,0 +1,34 @@
+module tb();
+ reg clk;
+ reg reset;
+ reg enable;
+ reg up_down;
+
+ wire [7 : 0] count;
+ wire overflow;
+
+initial begin
+ $monitor("rst %b en %b updown %b cnt %b overflow %b",
+ reset,enable,up_down,count, overflow);
+ clk = 0;
+ reset = 1;
+ enable = 0;
+ up_down = 0;
+ #10 reset = 0;
+ #1 enable = 1;
+ #20 up_down = 1;
+ #30 $finish;
+end
+
+always #1 clk = ~clk;
+
+lfsr_updown U(
+.clk ( clk ),
+.reset ( reset ),
+.enable ( enable ),
+.up_down ( up_down ),
+.count ( count ),
+.overflow ( overflow )
+);
+
+endmodule
diff --git a/examples/intel/asicworld_lfsr/run_cycloneiv b/examples/intel/asicworld_lfsr/run_cycloneiv
new file mode 100755
index 00000000..c7498bde
--- /dev/null
+++ b/examples/intel/asicworld_lfsr/run_cycloneiv
@@ -0,0 +1,2 @@
+#!/bin/env bash
+yosys -p "synth_intel -family cycloneiv -top lfsr_updown -vqm top.vqm" lfsr_updown.v
diff --git a/examples/intel/asicworld_lfsr/run_max10 b/examples/intel/asicworld_lfsr/run_max10
new file mode 100755
index 00000000..b75d552b
--- /dev/null
+++ b/examples/intel/asicworld_lfsr/run_max10
@@ -0,0 +1,2 @@
+#!/bin/env bash
+yosys -p "synth_intel -family max10 -top lfsr_updown -vqm top.vqm" lfsr_updown.v
diff --git a/examples/intel/asicworld_lfsr/runme_postsynth b/examples/intel/asicworld_lfsr/runme_postsynth
new file mode 100755
index 00000000..c3b26b03
--- /dev/null
+++ b/examples/intel/asicworld_lfsr/runme_postsynth
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+iverilog -D POST_IMPL -o verif_post -s tb lfsr_updown_tb.v top.vqm $(yosys-config --datdir/altera_intel/max10/cells_comb_max10.v)
+vvp -N verif_post
+
diff --git a/examples/intel/asicworld_lfsr/runme_presynth b/examples/intel/asicworld_lfsr/runme_presynth
new file mode 100755
index 00000000..51118bb4
--- /dev/null
+++ b/examples/intel/asicworld_lfsr/runme_presynth
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+iverilog -o presynth lfsr_updown_tb.v lfsr_updown.v &&\
+
+vvp -N presynth \ No newline at end of file
diff --git a/examples/osu035/.gitignore b/examples/osu035/.gitignore
new file mode 100644
index 00000000..3abf340b
--- /dev/null
+++ b/examples/osu035/.gitignore
@@ -0,0 +1,3 @@
+osu035_stdcells.lib
+example.yslog
+example.edif
diff --git a/examples/osu035/Makefile b/examples/osu035/Makefile
new file mode 100644
index 00000000..2bb8162b
--- /dev/null
+++ b/examples/osu035/Makefile
@@ -0,0 +1,13 @@
+
+example.edif: example.ys example.v example.constr osu035_stdcells.lib
+ yosys -l example.yslog -q example.ys
+
+osu035_stdcells.lib:
+ rm -f osu035_stdcells.lib.part osu035_stdcells.lib
+ wget -O osu035_stdcells.lib.part https://vlsiarch.ecen.okstate.edu/flows/MOSIS_SCMOS/latest/cadence/lib/ami035/signalstorm/osu035_stdcells.lib
+ mv osu035_stdcells.lib.part osu035_stdcells.lib
+
+clean:
+ rm -f osu035_stdcells.lib
+ rm -f example.yslog example.edif
+
diff --git a/examples/osu035/example.constr b/examples/osu035/example.constr
new file mode 100644
index 00000000..eb2c6e8d
--- /dev/null
+++ b/examples/osu035/example.constr
@@ -0,0 +1,2 @@
+set_driving_cell INVX1
+set_load 0.015
diff --git a/examples/osu035/example.v b/examples/osu035/example.v
new file mode 100644
index 00000000..0f043e5f
--- /dev/null
+++ b/examples/osu035/example.v
@@ -0,0 +1,3 @@
+module top (input clk, input [7:0] a, b, output reg [15:0] c);
+ always @(posedge clk) c <= a * b;
+endmodule
diff --git a/examples/osu035/example.ys b/examples/osu035/example.ys
new file mode 100644
index 00000000..6821ef42
--- /dev/null
+++ b/examples/osu035/example.ys
@@ -0,0 +1,11 @@
+read_verilog example.v
+read_liberty -lib osu035_stdcells.lib
+
+synth -top top
+
+dfflibmap -liberty osu035_stdcells.lib
+abc -D 10000 -constr example.constr -liberty osu035_stdcells.lib
+opt_clean
+
+stat -liberty osu035_stdcells.lib
+write_edif example.edif
diff --git a/examples/smtbmc/.gitignore b/examples/smtbmc/.gitignore
index a3f4f0f2..278f5ebf 100644
--- a/examples/smtbmc/.gitignore
+++ b/examples/smtbmc/.gitignore
@@ -20,3 +20,5 @@ demo6.smt2
demo6.yslog
demo7.smt2
demo7.yslog
+demo8.smt2
+demo8.yslog
diff --git a/examples/smtbmc/Makefile b/examples/smtbmc/Makefile
index 2f7060bd..96fa058d 100644
--- a/examples/smtbmc/Makefile
+++ b/examples/smtbmc/Makefile
@@ -1,5 +1,5 @@
-all: demo1 demo2 demo3 demo4 demo5 demo6 demo7
+all: demo1 demo2 demo3 demo4 demo5 demo6 demo7 demo8
demo1: demo1.smt2
yosys-smtbmc --dump-vcd demo1.vcd demo1.smt2
@@ -25,6 +25,9 @@ demo6: demo6.smt2
demo7: demo7.smt2
yosys-smtbmc -t 10 demo7.smt2
+demo8: demo8.smt2
+ yosys-smtbmc -s z3 -t 1 -g demo8.smt2
+
demo1.smt2: demo1.v
yosys -ql demo1.yslog -p 'read_verilog -formal demo1.v; prep -top demo1 -nordff; write_smt2 -wires demo1.smt2'
@@ -46,6 +49,9 @@ demo6.smt2: demo6.v
demo7.smt2: demo7.v
yosys -ql demo7.yslog -p 'read_verilog -formal demo7.v; prep -top demo7 -nordff; write_smt2 -wires demo7.smt2'
+demo8.smt2: demo8.v
+ yosys -ql demo8.yslog -p 'read_verilog -formal demo8.v; prep -top demo8 -nordff; write_smt2 -stbv -wires demo8.smt2'
+
clean:
rm -f demo1.yslog demo1.smt2 demo1.vcd
rm -f demo2.yslog demo2.smt2 demo2.vcd demo2.smtc demo2_tb.v demo2_tb demo2_tb.vcd
@@ -54,6 +60,7 @@ clean:
rm -f demo5.yslog demo5.smt2 demo5.vcd
rm -f demo6.yslog demo6.smt2
rm -f demo7.yslog demo7.smt2
+ rm -f demo8.yslog demo8.smt2
-.PHONY: demo1 demo2 demo3 demo4 demo5 demo6 demo7 clean
+.PHONY: demo1 demo2 demo3 demo4 demo5 demo6 demo7 demo8 clean
diff --git a/examples/smtbmc/demo2.v b/examples/smtbmc/demo2.v
index 34745e89..0cf529a4 100644
--- a/examples/smtbmc/demo2.v
+++ b/examples/smtbmc/demo2.v
@@ -9,7 +9,7 @@
module demo2(input clk, input [4:0] addr, output reg [31:0] data);
reg [31:0] mem [0:31];
- always @(posedge clk)
+ always @(negedge clk)
data <= mem[addr];
reg [31:0] used_addr = 0;
diff --git a/examples/smtbmc/demo8.v b/examples/smtbmc/demo8.v
new file mode 100644
index 00000000..c4c396cd
--- /dev/null
+++ b/examples/smtbmc/demo8.v
@@ -0,0 +1,12 @@
+// Simple exists-forall demo
+
+module demo8;
+ wire [7:0] prime = $anyconst;
+ wire [3:0] factor = $allconst;
+
+ always @* begin
+ if (1 < factor && factor < prime)
+ assume((prime % factor) != 0);
+ assume(prime > 1);
+ end
+endmodule
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 92513a24..e79be953 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -44,7 +44,7 @@ namespace AST {
// instanciate global variables (private API)
namespace AST_INTERNAL {
- bool flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
+ bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire;
AstNode *current_ast, *current_ast_mod;
std::map<std::string, AstNode*> current_scope;
@@ -84,6 +84,9 @@ std::string AST::type2str(AstNodeType type)
X(AST_PREFIX)
X(AST_ASSERT)
X(AST_ASSUME)
+ X(AST_LIVE)
+ X(AST_FAIR)
+ X(AST_COVER)
X(AST_FCALL)
X(AST_TO_BITS)
X(AST_TO_SIGNED)
@@ -168,8 +171,8 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id)
AstNode *attr = attributes.at(id);
if (attr->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- id.c_str(), attr->filename.c_str(), attr->linenum);
+ log_file_error(attr->filename, attr->linenum, "Attribute `%s' with non-constant value!\n",
+ id.c_str());
return attr->integer != 0;
}
@@ -188,8 +191,10 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
is_input = false;
is_output = false;
is_reg = false;
+ is_logic = false;
is_signed = false;
is_string = false;
+ was_checked = false;
range_valid = false;
range_swapped = false;
port_id = 0;
@@ -209,7 +214,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
}
// create a (deep recursive) copy of a node
-AstNode *AstNode::clone()
+AstNode *AstNode::clone() const
{
AstNode *that = new AstNode;
*that = *this;
@@ -221,7 +226,7 @@ AstNode *AstNode::clone()
}
// create a (deep recursive) copy of a node use 'other' as target root node
-void AstNode::cloneInto(AstNode *other)
+void AstNode::cloneInto(AstNode *other) const
{
AstNode *tmp = clone();
other->delete_children();
@@ -251,7 +256,7 @@ AstNode::~AstNode()
// create a nice text representation of the node
// (traverse tree by recursion, use 'other' pointer for diffing two AST trees)
-void AstNode::dumpAst(FILE *f, std::string indent)
+void AstNode::dumpAst(FILE *f, std::string indent) const
{
if (f == NULL) {
for (auto f : log_files)
@@ -262,10 +267,12 @@ void AstNode::dumpAst(FILE *f, std::string indent)
std::string type_name = type2str(type);
fprintf(f, "%s%s <%s:%d>", indent.c_str(), type_name.c_str(), filename.c_str(), linenum);
- if (id2ast)
- fprintf(f, " [%p -> %p]", this, id2ast);
- else
- fprintf(f, " [%p]", this);
+ if (!flag_no_dump_ptr) {
+ if (id2ast)
+ fprintf(f, " [%p -> %p]", this, id2ast);
+ else
+ fprintf(f, " [%p]", this);
+ }
if (!str.empty())
fprintf(f, " str='%s'", str.c_str());
@@ -282,7 +289,9 @@ void AstNode::dumpAst(FILE *f, std::string indent)
fprintf(f, " input");
if (is_output)
fprintf(f, " output");
- if (is_reg)
+ if (is_logic)
+ fprintf(f, " logic");
+ if (is_reg) // this is an AST dump, not Verilog - if we see "logic reg" that's fine.
fprintf(f, " reg");
if (is_signed)
fprintf(f, " signed");
@@ -330,7 +339,7 @@ static std::string id2vl(std::string txt)
}
// dump AST node as Verilog pseudo-code
-void AstNode::dumpVlog(FILE *f, std::string indent)
+void AstNode::dumpVlog(FILE *f, std::string indent) const
{
bool first = true;
std::string txt;
@@ -649,6 +658,8 @@ bool AstNode::operator==(const AstNode &other) const
return false;
if (is_output != other.is_output)
return false;
+ if (is_logic != other.is_logic)
+ return false;
if (is_reg != other.is_reg)
return false;
if (is_signed != other.is_signed)
@@ -752,7 +763,7 @@ AstNode *AstNode::mkconst_str(const std::string &str)
return node;
}
-bool AstNode::bits_only_01()
+bool AstNode::bits_only_01() const
{
for (auto bit : bits)
if (bit != RTLIL::S0 && bit != RTLIL::S1)
@@ -803,7 +814,7 @@ RTLIL::Const AstNode::asParaConst()
return val;
}
-bool AstNode::asBool()
+bool AstNode::asBool() const
{
log_assert(type == AST_CONSTANT);
for (auto &bit : bits)
@@ -812,7 +823,7 @@ bool AstNode::asBool()
return false;
}
-int AstNode::isConst()
+int AstNode::isConst() const
{
if (type == AST_CONSTANT)
return 1;
@@ -952,8 +963,8 @@ static AstModule* process_module(AstNode *ast, bool defer)
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), ast->filename.c_str(), ast->linenum);
+ log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
current_module->attributes[attr.first] = attr.second->asAttrConst();
}
for (size_t i = 0; i < ast->children.size(); i++) {
@@ -999,12 +1010,13 @@ static AstModule* process_module(AstNode *ast, bool defer)
}
// create AstModule instances for all modules in the AST tree and add them to 'design'
-void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool dump_vlog, bool dump_rtlil,
- bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool ignore_redef, bool defer, bool autowire)
+void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog, bool dump_rtlil,
+ bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire)
{
current_ast = ast;
flag_dump_ast1 = dump_ast1;
flag_dump_ast2 = dump_ast2;
+ flag_no_dump_ptr = no_dump_ptr;
flag_dump_vlog = dump_vlog;
flag_dump_rtlil = dump_rtlil;
flag_nolatches = nolatches;
@@ -1016,14 +1028,12 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
flag_icells = icells;
flag_autowire = autowire;
- std::vector<AstNode*> global_decls;
-
log_assert(current_ast->type == AST_DESIGN);
for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++)
{
if ((*it)->type == AST_MODULE)
{
- for (auto n : global_decls)
+ for (auto n : design->verilog_globals)
(*it)->children.push_back(n->clone());
for (auto n : design->verilog_packages){
@@ -1041,12 +1051,20 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
(*it)->str = "$abstract" + (*it)->str;
if (design->has((*it)->str)) {
- if (!ignore_redef)
- log_error("Re-definition of module `%s' at %s:%d!\n",
+ RTLIL::Module *existing_mod = design->module((*it)->str);
+ if (!nooverwrite && !overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
+ log_file_error((*it)->filename, (*it)->linenum, "Re-definition of module `%s'!\n",
+ (*it)->str.c_str());
+ } else if (nooverwrite) {
+ log("Ignoring re-definition of module `%s' at %s:%d.\n",
(*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
- log("Ignoring re-definition of module `%s' at %s:%d!\n",
- (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
- continue;
+ continue;
+ } else {
+ log("Replacing existing%s module `%s' at %s:%d.\n",
+ existing_mod->get_bool_attribute("\\blackbox") ? " blackbox" : "",
+ (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
+ design->remove(existing_mod);
+ }
}
design->add(process_module(*it, defer));
@@ -1054,7 +1072,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
else if ((*it)->type == AST_PACKAGE)
design->verilog_packages.push_back((*it)->clone());
else
- global_decls.push_back(*it);
+ design->verilog_globals.push_back((*it)->clone());
}
}
@@ -1066,7 +1084,7 @@ AstModule::~AstModule()
}
// create a new parametric module (when needed) and return the name of the generated module
-RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters)
+RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool)
{
std::string stripped_name = name.str();
@@ -1105,7 +1123,10 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
rewrite_parameter:
para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
delete child->children.at(0);
- child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, (parameters[para_id].flags & RTLIL::CONST_FLAG_SIGNED) != 0);
+ if ((parameters[para_id].flags & RTLIL::CONST_FLAG_STRING) != 0)
+ child->children[0] = AstNode::mkconst_str(parameters[para_id].decode_string());
+ else
+ child->children[0] = AstNode::mkconst_bits(parameters[para_id].bits, (parameters[para_id].flags & RTLIL::CONST_FLAG_SIGNED) != 0);
parameters.erase(para_id);
continue;
}
@@ -1115,8 +1136,16 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
goto rewrite_parameter;
}
}
- if (parameters.size() > 0)
- log_error("Requested parameter `%s' does not exist in module `%s'!\n", parameters.begin()->first.c_str(), stripped_name.c_str());
+
+ for (auto param : parameters) {
+ AstNode *defparam = new AstNode(AST_DEFPARAM, new AstNode(AST_IDENTIFIER));
+ defparam->children[0]->str = param.first.str();
+ if ((param.second.flags & RTLIL::CONST_FLAG_STRING) != 0)
+ defparam->children.push_back(AstNode::mkconst_str(param.second.decode_string()));
+ else
+ defparam->children.push_back(AstNode::mkconst_bits(param.second.bits, (param.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0));
+ new_ast->children.push_back(defparam);
+ }
std::string modname;
@@ -1177,4 +1206,3 @@ void AST::use_internal_line_num()
}
YOSYS_NAMESPACE_END
-
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index cd6e264e..7e97bdb3 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -1,4 +1,4 @@
-/*
+/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
@@ -65,6 +65,9 @@ namespace AST
AST_PREFIX,
AST_ASSERT,
AST_ASSUME,
+ AST_LIVE,
+ AST_FAIR,
+ AST_COVER,
AST_FCALL,
AST_TO_BITS,
@@ -165,7 +168,7 @@ namespace AST
// node content - most of it is unused in most node types
std::string str;
std::vector<RTLIL::State> bits;
- bool is_input, is_output, is_reg, is_signed, is_string, range_valid, range_swapped;
+ bool is_input, is_output, is_reg, is_logic, is_signed, is_string, range_valid, range_swapped, was_checked;
int port_id, range_left, range_right;
uint32_t integer;
double realvalue;
@@ -187,8 +190,8 @@ namespace AST
// creating and deleting nodes
AstNode(AstNodeType type = AST_NONE, AstNode *child1 = NULL, AstNode *child2 = NULL, AstNode *child3 = NULL);
- AstNode *clone();
- void cloneInto(AstNode *other);
+ AstNode *clone() const;
+ void cloneInto(AstNode *other) const;
void delete_children();
~AstNode();
@@ -231,8 +234,8 @@ namespace AST
AstNode *eval_const_function(AstNode *fcall);
// create a human-readable text representation of the AST (for debugging)
- void dumpAst(FILE *f, std::string indent);
- void dumpVlog(FILE *f, std::string indent);
+ void dumpAst(FILE *f, std::string indent) const;
+ void dumpVlog(FILE *f, std::string indent) const;
// used by genRTLIL() for detecting expression width and sign
void detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real = NULL);
@@ -261,27 +264,27 @@ namespace AST
RTLIL::Const asAttrConst();
RTLIL::Const asParaConst();
uint64_t asInt(bool is_signed);
- bool bits_only_01();
- bool asBool();
+ bool bits_only_01() const;
+ bool asBool() const;
// helper functions for real valued const eval
- int isConst(); // return '1' for AST_CONSTANT and '2' for AST_REALVALUE
+ int isConst() const; // return '1' for AST_CONSTANT and '2' for AST_REALVALUE
double asReal(bool is_signed);
RTLIL::Const realAsConst(int width);
};
// process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code
- void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool dump_vlog, bool dump_rtlil, bool nolatches, bool nomeminit,
- bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool ignore_redef, bool defer, bool autowire);
+ void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog, bool dump_rtlil, bool nolatches, bool nomeminit,
+ bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire);
// parametric modules are supported directly by the AST library
// therefore we need our own derivate of RTLIL::Module with overloaded virtual functions
struct AstModule : RTLIL::Module {
AstNode *ast;
bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire;
- virtual ~AstModule();
- virtual RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters);
- virtual RTLIL::Module *clone() const;
+ ~AstModule() YS_OVERRIDE;
+ RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE;
+ RTLIL::Module *clone() const YS_OVERRIDE;
};
// this must be set by the language frontend before parsing the sources
@@ -302,7 +305,7 @@ namespace AST
namespace AST_INTERNAL
{
// internal state variables
- extern bool flag_dump_ast1, flag_dump_ast2, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
+ extern bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
extern bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire;
extern AST::AstNode *current_ast, *current_ast_mod;
extern std::map<std::string, AST::AstNode*> current_scope;
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index db8d7409..0f7e910f 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -55,8 +55,8 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_wi
if (gen_attributes)
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), that->filename.c_str(), that->linenum);
+ log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -89,8 +89,8 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
if (that != NULL)
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), that->filename.c_str(), that->linenum);
+ log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -117,8 +117,8 @@ static RTLIL::SigSpec binop2rtlil(AstNode *that, std::string type, int result_wi
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), that->filename.c_str(), that->linenum);
+ log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -152,8 +152,8 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), that->filename.c_str(), that->linenum);
+ log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -207,8 +207,8 @@ struct AST_INTERNAL::ProcessGenerator
proc->name = stringf("$proc$%s:%d$%d", always->filename.c_str(), always->linenum, autoidx++);
for (auto &attr : always->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), always->filename.c_str(), always->linenum);
+ log_file_error(always->filename, always->linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
proc->attributes[attr.first] = attr.second->asAttrConst();
}
current_module->processes[proc->name] = proc;
@@ -223,16 +223,22 @@ struct AST_INTERNAL::ProcessGenerator
bool found_global_syncs = false;
bool found_anyedge_syncs = false;
for (auto child : always->children)
+ {
+ if ((child->type == AST_POSEDGE || child->type == AST_NEGEDGE) && GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER &&
+ child->children.at(0)->id2ast && child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute("\\gclk")) {
+ found_global_syncs = true;
+ }
if (child->type == AST_EDGE) {
if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->str == "\\$global_clock")
found_global_syncs = true;
else
found_anyedge_syncs = true;
}
+ }
if (found_anyedge_syncs) {
if (found_global_syncs)
- log_error("Found non-synthesizable event list at %s:%d!\n", always->filename.c_str(), always->linenum);
+ log_file_error(always->filename, always->linenum, "Found non-synthesizable event list!\n");
log("Note: Assuming pure combinatorial block at %s:%d in\n", always->filename.c_str(), always->linenum);
log("compliance with IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002. Recommending\n");
log("use of @* instead of @(...) for better match of synthesis and simulation.\n");
@@ -242,14 +248,17 @@ struct AST_INTERNAL::ProcessGenerator
bool found_clocked_sync = false;
for (auto child : always->children)
if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE) {
+ if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->id2ast &&
+ child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute("\\gclk"))
+ continue;
found_clocked_sync = true;
if (found_global_syncs || found_anyedge_syncs)
- log_error("Found non-synthesizable event list at %s:%d!\n", always->filename.c_str(), always->linenum);
+ log_file_error(always->filename, always->linenum, "Found non-synthesizable event list!\n");
RTLIL::SyncRule *syncrule = new RTLIL::SyncRule;
syncrule->type = child->type == AST_POSEDGE ? RTLIL::STp : RTLIL::STn;
syncrule->signal = child->children[0]->genRTLIL();
if (GetSize(syncrule->signal) != 1)
- log_error("Found posedge/negedge event on a signal that is not 1 bit wide at %s:%d!\n", always->filename.c_str(), always->linenum);
+ log_file_error(always->filename, always->linenum, "Found posedge/negedge event on a signal that is not 1 bit wide!\n");
addChunkActions(syncrule->actions, subst_lvalue_from, subst_lvalue_to, true);
proc->syncs.push_back(syncrule);
}
@@ -471,8 +480,8 @@ struct AST_INTERNAL::ProcessGenerator
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), ast->filename.c_str(), ast->linenum);
+ log_file_error(ast->filename, ast->linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
sw->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -540,12 +549,12 @@ struct AST_INTERNAL::ProcessGenerator
break;
case AST_WIRE:
- log_error("Found wire declaration in block without label at at %s:%d!\n", ast->filename.c_str(), ast->linenum);
+ log_file_error(ast->filename, ast->linenum, "Found wire declaration in block without label!\n");
break;
case AST_PARAMETER:
case AST_LOCALPARAM:
- log_error("Found parameter declaration in block without label at at %s:%d!\n", ast->filename.c_str(), ast->linenum);
+ log_file_error(ast->filename, ast->linenum, "Found parameter declaration in block without label!\n");
break;
case AST_NONE:
@@ -554,6 +563,8 @@ struct AST_INTERNAL::ProcessGenerator
break;
default:
+ // ast->dumpAst(NULL, "ast> ");
+ // current_ast_mod->dumpAst(NULL, "mod> ");
log_abort();
}
}
@@ -591,7 +602,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (id_ast == NULL && current_scope.count(str))
id_ast = current_scope.at(str);
if (!id_ast)
- log_error("Failed to resolve identifier %s for width detection at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to resolve identifier %s for width detection!\n", str.c_str());
if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM) {
if (id_ast->children.size() > 1 && id_ast->children[1]->range_valid) {
this_width = id_ast->children[1]->range_left - id_ast->children[1]->range_right + 1;
@@ -601,7 +612,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (id_ast->children[0]->type == AST_CONSTANT)
this_width = id_ast->children[0]->bits.size();
else
- log_error("Failed to detect width for parameter %s at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to detect width for parameter %s!\n", str.c_str());
if (children.size() != 0)
range = children[0];
} else if (id_ast->type == AST_WIRE || id_ast->type == AST_AUTOWIRE) {
@@ -613,7 +624,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
// log("---\n");
// id_ast->dumpAst(NULL, "decl> ");
// dumpAst(NULL, "ref> ");
- log_error("Failed to detect width of signal access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to detect width of signal access `%s'!\n", str.c_str());
}
} else {
this_width = id_ast->range_left - id_ast->range_right + 1;
@@ -624,10 +635,10 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
this_width = 32;
} else if (id_ast->type == AST_MEMORY) {
if (!id_ast->children[0]->range_valid)
- log_error("Failed to detect width of memory access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", str.c_str());
this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1;
} else
- log_error("Failed to detect width for identifier %s at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to detect width for identifier %s!\n", str.c_str());
if (range) {
if (range->children.size() == 1)
this_width = 1;
@@ -637,8 +648,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
- log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
+ str.c_str());
this_width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
delete left_at_zero_ast;
delete right_at_zero_ast;
@@ -654,7 +665,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
case AST_TO_BITS:
while (children[0]->simplify(true, false, false, 1, -1, false, false) == true) { }
if (children[0]->type != AST_CONSTANT)
- log_error("Left operand of tobits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Left operand of tobits expression is not constant!\n");
children[1]->detectSignWidthWorker(sub_width_hint, sign_hint);
width_hint = max(width_hint, children[0]->bitsAsConst().as_int());
break;
@@ -682,7 +693,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
case AST_REPLICATE:
while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { }
if (children[0]->type != AST_CONSTANT)
- log_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Left operand of replicate expression is not constant!\n");
children[1]->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
width_hint = max(width_hint, children[0]->bitsAsConst().as_int() * sub_width_hint);
sign_hint = false;
@@ -756,18 +767,18 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (!id2ast->is_signed)
sign_hint = false;
if (!id2ast->children[0]->range_valid)
- log_error("Failed to detect width of memory access `%s' at %s:%d!\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to detect width of memory access `%s'!\n", str.c_str());
this_width = id2ast->children[0]->range_left - id2ast->children[0]->range_right + 1;
width_hint = max(width_hint, this_width);
break;
case AST_FCALL:
- if (str == "\\$anyconst" || str == "\\$anyseq") {
+ if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq") {
if (GetSize(children) == 1) {
while (children[0]->simplify(true, false, false, 1, -1, false, true) == true) { }
if (children[0]->type != AST_CONSTANT)
- log_error("System function %s called with non-const argument at %s:%d!\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s called with non-const argument!\n",
+ RTLIL::unescape_id(str).c_str());
width_hint = max(width_hint, int(children[0]->asInt(true)));
}
break;
@@ -788,8 +799,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
default:
for (auto f : log_files)
current_ast->dumpAst(f, "verilog-ast> ");
- log_error("Don't know how to detect sign and width for %s node at %s:%d!\n",
- type2str(type).c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Don't know how to detect sign and width for %s node!\n",
+ type2str(type).c_str());
}
if (*found_real)
@@ -852,11 +863,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// create an RTLIL::Wire for an AST_WIRE node
case AST_WIRE: {
if (current_module->wires_.count(str) != 0)
- log_error("Re-definition of signal `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Re-definition of signal `%s'!\n",
+ str.c_str());
if (!range_valid)
- log_error("Signal `%s' with non-constant width at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Signal `%s' with non-constant width!\n",
+ str.c_str());
log_assert(range_left >= range_right || (range_left == -1 && range_right == 0));
@@ -870,8 +881,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
wire->attributes[attr.first] = attr.second->asAttrConst();
}
}
@@ -880,16 +891,16 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// create an RTLIL::Memory for an AST_MEMORY node
case AST_MEMORY: {
if (current_module->memories.count(str) != 0)
- log_error("Re-definition of memory `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Re-definition of memory `%s'!\n",
+ str.c_str());
log_assert(children.size() >= 2);
log_assert(children[0]->type == AST_RANGE);
log_assert(children[1]->type == AST_RANGE);
if (!children[0]->range_valid || !children[1]->range_valid)
- log_error("Memory `%s' with non-constant width or size at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Memory `%s' with non-constant width or size!\n",
+ str.c_str());
RTLIL::Memory *memory = new RTLIL::Memory;
memory->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
@@ -906,8 +917,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
memory->attributes[attr.first] = attr.second->asAttrConst();
}
}
@@ -926,8 +937,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
case AST_REALVALUE:
{
RTLIL::SigSpec sig = realAsConst(width_hint);
- log_warning("converting real value %e to binary %s at %s:%d.\n",
- realvalue, log_signal(sig), filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "converting real value %e to binary %s.\n",
+ realvalue, log_signal(sig));
return sig;
}
@@ -947,25 +958,25 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
wire->name = str;
if (flag_autowire)
- log_warning("Identifier `%s' is implicitly declared at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "Identifier `%s' is implicitly declared.\n", str.c_str());
else
- log_error("Identifier `%s' is implicitly declared at %s:%d and `default_nettype is set to none.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
}
else if (id2ast->type == AST_PARAMETER || id2ast->type == AST_LOCALPARAM) {
if (id2ast->children[0]->type != AST_CONSTANT)
- log_error("Parameter %s does not evaluate to constant value at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Parameter %s does not evaluate to constant value!\n",
+ str.c_str());
chunk = RTLIL::Const(id2ast->children[0]->bits);
goto use_const_chunk;
}
else if (!id2ast || (id2ast->type != AST_WIRE && id2ast->type != AST_AUTOWIRE &&
id2ast->type != AST_MEMORY) || current_module->wires_.count(str) == 0)
- log_error("Identifier `%s' doesn't map to any signal at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Identifier `%s' doesn't map to any signal!\n",
+ str.c_str());
if (id2ast->type == AST_MEMORY)
- log_error("Identifier `%s' does map to an unexpanded memory at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Identifier `%s' does map to an unexpanded memory!\n",
+ str.c_str());
wire = current_module->wires_[str];
chunk.wire = wire;
@@ -983,8 +994,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
while (left_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
while (right_at_zero_ast->simplify(true, true, false, 1, -1, false, false)) { }
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
- log_error("Unsupported expression on dynamic range select on signal `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Unsupported expression on dynamic range select on signal `%s'!\n",
+ str.c_str());
int width = left_at_zero_ast->integer - right_at_zero_ast->integer + 1;
AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ?
children[0]->children[1]->clone() : children[0]->children[0]->clone());
@@ -1012,11 +1023,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
chunk.offset = (id2ast->range_left - id2ast->range_right + 1) - (chunk.offset + chunk.width);
if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) {
if (chunk.width == 1)
- log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting result bit to undef.\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting result bit to undef.\n",
+ str.c_str());
else
- log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting all %d result bits to undef.\n",
- str.c_str(), filename.c_str(), linenum, chunk.width);
+ log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting all %d result bits to undef.\n",
+ str.c_str(), chunk.width);
chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width);
} else {
if (chunk.width + chunk.offset > source_width) {
@@ -1029,11 +1040,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
chunk.offset += add_undef_bits_lsb;
}
if (add_undef_bits_lsb)
- log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d LSB bits to undef.\n",
- str.c_str(), filename.c_str(), linenum, add_undef_bits_lsb);
+ log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d LSB bits to undef.\n",
+ str.c_str(), add_undef_bits_lsb);
if (add_undef_bits_msb)
- log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d MSB bits to undef.\n",
- str.c_str(), filename.c_str(), linenum, add_undef_bits_msb);
+ log_file_warning(filename, linenum, "Range select out of bounds on signal `%s': Setting %d MSB bits to undef.\n",
+ str.c_str(), add_undef_bits_msb);
}
}
}
@@ -1072,7 +1083,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
RTLIL::SigSpec left = children[0]->genRTLIL();
RTLIL::SigSpec right = children[1]->genRTLIL();
if (!left.is_fully_const())
- log_error("Left operand of replicate expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Left operand of replicate expression is not constant!\n");
int count = left.as_int();
RTLIL::SigSpec sig;
for (int i = 0; i < count; i++)
@@ -1289,6 +1300,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(0);
cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0);
+ if (!sign_hint)
+ is_signed = false;
+
return RTLIL::SigSpec(wire);
}
@@ -1308,7 +1322,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
int num_words = 1;
if (type == AST_MEMINIT) {
if (children[2]->type != AST_CONSTANT)
- log_error("Memory init with non-constant word count at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Memory init with non-constant word count!\n");
num_words = int(children[2]->asInt(false));
cell->parameters["\\WORDS"] = RTLIL::Const(num_words);
}
@@ -1336,9 +1350,16 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// generate $assert cells
case AST_ASSERT:
case AST_ASSUME:
+ case AST_LIVE:
+ case AST_FAIR:
+ case AST_COVER:
{
- const char *celltype = "$assert";
+ const char *celltype = nullptr;
+ if (type == AST_ASSERT) celltype = "$assert";
if (type == AST_ASSUME) celltype = "$assume";
+ if (type == AST_LIVE) celltype = "$live";
+ if (type == AST_FAIR) celltype = "$fair";
+ if (type == AST_COVER) celltype = "$cover";
log_assert(children.size() == 2);
@@ -1358,8 +1379,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
@@ -1380,10 +1401,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
new_left.append(left[i]);
new_right.append(right[i]);
}
- log_warning("Ignoring assignment to constant bits at %s:%d:\n"
- " old assignment: %s = %s\n new assignment: %s = %s.\n",
- filename.c_str(), linenum, log_signal(left), log_signal(right),
- log_signal(new_left), log_signal(new_right));
+ log_file_warning(filename, linenum, "Ignoring assignment to constant bits:\n"
+ " old assignment: %s = %s\n new assignment: %s = %s.\n",
+ log_signal(left), log_signal(right),
+ log_signal(new_left), log_signal(new_right));
left = new_left;
right = new_right;
}
@@ -1397,8 +1418,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
int port_counter = 0, para_counter = 0;
if (current_module->count_id(str) != 0)
- log_error("Re-definition of cell `%s' at %s:%d!\n",
- str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Re-definition of cell `%s'!\n", str.c_str());
RTLIL::Cell *cell = current_module->addCell(str, "");
cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
@@ -1414,16 +1434,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (child->type == AST_PARASET) {
IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str;
if (child->children[0]->type == AST_REALVALUE) {
- log_warning("Replacing floating point parameter %s.%s = %f with string at %s:%d.\n",
- log_id(cell), log_id(paraname), child->children[0]->realvalue,
- filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "Replacing floating point parameter %s.%s = %f with string.\n",
+ log_id(cell), log_id(paraname), child->children[0]->realvalue);
auto strnode = AstNode::mkconst_str(stringf("%f", child->children[0]->realvalue));
strnode->cloneInto(child->children[0]);
delete strnode;
}
if (child->children[0]->type != AST_CONSTANT)
- log_error("Parameter %s.%s with non-constant value at %s:%d!\n",
- log_id(cell), log_id(paraname), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Parameter %s.%s with non-constant value!\n",
+ log_id(cell), log_id(paraname));
cell->parameters[paraname] = child->children[0]->asParaConst();
continue;
}
@@ -1444,8 +1463,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
for (auto &attr : attributes) {
if (attr.second->type != AST_CONSTANT)
- log_error("Attribute `%s' with non-constant value at %s:%d!\n",
- attr.first.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n",
+ attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
}
@@ -1466,30 +1485,37 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
} break;
case AST_FCALL: {
- if (str == "\\$anyconst" || str == "\\$anyseq")
+ if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq")
{
string myid = stringf("%s$%d", str.c_str() + 1, autoidx++);
int width = width_hint;
if (GetSize(children) > 1)
- log_error("System function %s got %d arguments, expected 1 or 0 at %s:%d.\n",
- RTLIL::unescape_id(str).c_str(), GetSize(children), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s got %d arguments, expected 1 or 0.\n",
+ RTLIL::unescape_id(str).c_str(), GetSize(children));
if (GetSize(children) == 1) {
if (children[0]->type != AST_CONSTANT)
- log_error("System function %s called with non-const argument at %s:%d!\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System function %s called with non-const argument!\n",
+ RTLIL::unescape_id(str).c_str());
width = children[0]->asInt(true);
}
if (width <= 0)
- log_error("Failed to detect width of %s at %s:%d!\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to detect width of %s!\n",
+ RTLIL::unescape_id(str).c_str());
Cell *cell = current_module->addCell(myid, str.substr(1));
cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
cell->parameters["\\WIDTH"] = width;
+ if (attributes.count("\\reg")) {
+ auto &attr = attributes.at("\\reg");
+ if (attr->type != AST_CONSTANT)
+ log_file_error(filename, linenum, "Attribute `reg' with non-constant value!\n");
+ cell->attributes["\\reg"] = attr->asAttrConst();
+ }
+
Wire *wire = current_module->addWire(myid + "_wire", width);
wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
cell->setPort("\\Y", wire);
@@ -1504,8 +1530,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
for (auto f : log_files)
current_ast->dumpAst(f, "verilog-ast> ");
type_name = type2str(type);
- log_error("Don't know how to generate RTLIL code for %s node at %s:%d!\n",
- type_name.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Don't know how to generate RTLIL code for %s node!\n",
+ type_name.c_str());
}
return RTLIL::SigSpec();
@@ -1535,4 +1561,3 @@ RTLIL::SigSpec AstNode::genWidthRTLIL(int width, const dict<RTLIL::SigBit, RTLIL
}
YOSYS_NAMESPACE_END
-
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 9d5c75fe..04c429f7 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -177,13 +177,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
// note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list
if ((type == AST_FCALL || type == AST_TCALL) && (str == "$strobe" || str == "$monitor" || str == "$time" ||
str == "$dumpfile" || str == "$dumpvars" || str == "$dumpon" || str == "$dumpoff" || str == "$dumpall")) {
- log_warning("Ignoring call to system %s %s at %s:%d.\n", type == AST_FCALL ? "function" : "task", str.c_str(), filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str.c_str());
delete_children();
str = std::string();
}
if ((type == AST_TCALL) && (str == "$display" || str == "$write") && (!current_always || current_always->type != AST_INITIAL)) {
- log_warning("System task `%s' outside initial block is unsupported at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "System task `%s' outside initial block is unsupported.\n", str.c_str());
delete_children();
str = std::string();
}
@@ -195,14 +195,14 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
int nargs = GetSize(children);
if (nargs < 1)
- log_error("System task `%s' got %d arguments, expected >= 1 at %s:%d.\n",
- str.c_str(), int(children.size()), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System task `%s' got %d arguments, expected >= 1.\n",
+ str.c_str(), int(children.size()));
// First argument is the format string
AstNode *node_string = children[0];
while (node_string->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (node_string->type != AST_CONSTANT)
- log_error("Failed to evaluate system task `%s' with non-constant 1st argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to evaluate system task `%s' with non-constant 1st argument.\n", str.c_str());
std::string sformat = node_string->bitsAsConst().decode_string();
// Other arguments are placeholders. Process the string as we go through it
@@ -215,7 +215,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
// If there's no next character, that's a problem
if (i+1 >= sformat.length())
- log_error("System task `%s' called with `%%' at end of string at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System task `%s' called with `%%' at end of string.\n", str.c_str());
char cformat = sformat[++i];
@@ -239,13 +239,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
case 'x':
case 'X':
if (next_arg >= GetSize(children))
- log_error("Missing argument for %%%c format specifier in system task `%s' at %s:%d.\n",
- cformat, str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Missing argument for %%%c format specifier in system task `%s'.\n",
+ cformat, str.c_str());
node_arg = children[next_arg++];
while (node_arg->simplify(true, false, false, stage, width_hint, sign_hint, false)) { }
if (node_arg->type != AST_CONSTANT)
- log_error("Failed to evaluate system task `%s' with non-constant argument at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Failed to evaluate system task `%s' with non-constant argument.\n", str.c_str());
break;
case 'm':
@@ -253,7 +253,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
break;
default:
- log_error("System task `%s' called with invalid/unsupported format specifier at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "System task `%s' called with invalid/unsupported format specifier.\n", str.c_str());
break;
}
@@ -327,6 +327,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (node->type == AST_WIRE) {
if (this_wire_scope.count(node->str) > 0) {
AstNode *first_node = this_wire_scope[node->str];
+ if (first_node->is_input && node->is_reg)
+ goto wires_are_incompatible;
if (!node->is_input && !node->is_output && node->is_reg && node->children.size() == 0)
goto wires_are_compatible;
if (first_node->children.size() == 0 && node->children.size() == 1 && node->children[0]->type == AST_RANGE) {
@@ -361,6 +363,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
first_node->is_output = true;
if (node->is_reg)
first_node->is_reg = true;
+ if (node->is_logic)
+ first_node->is_logic = true;
if (node->is_signed)
first_node->is_signed = true;
for (auto &it : node->attributes) {
@@ -374,7 +378,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
continue;
wires_are_incompatible:
if (stage > 1)
- log_error("Incompatible re-declaration of wire %s at %s:%d.\n", node->str.c_str(), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Incompatible re-declaration of wire %s.\n", node->str.c_str());
continue;
}
this_wire_scope[node->str] = node;
@@ -387,7 +391,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
for (size_t i = 0; i < children.size(); i++) {
AstNode *node = children[i];
- if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE)
+ if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY)
while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM))
did_something = true;
}
@@ -401,13 +405,20 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_ALWAYS || type == AST_INITIAL)
{
+ if (current_always != nullptr)
+ log_file_error(filename, linenum, "Invalid nesting of always blocks and/or initializations.\n");
+
current_always = this;
current_always_clocked = false;
if (type == AST_ALWAYS)
- for (auto child : children)
+ for (auto child : children) {
if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE)
current_always_clocked = true;
+ if (child->type == AST_EDGE && GetSize(child->children) == 1 &&
+ child->children[0]->type == AST_IDENTIFIER && child->children[0]->str == "\\$global_clock")
+ current_always_clocked = true;
+ }
}
int backup_width_hint = width_hint;
@@ -433,6 +444,16 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
children[1]->detectSignWidth(width_hint, sign_hint);
width_hint = max(width_hint, backup_width_hint);
child_0_is_self_determined = true;
+ // test only once, before optimizations and memory mappings but after assignment LHS was mapped to an identifier
+ if (children[0]->id2ast && !children[0]->was_checked) {
+ if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && children[0]->id2ast->is_logic)
+ children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment
+ if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg)
+ log_warning("wire '%s' is assigned in a block at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum);
+ if (type == AST_ASSIGN && children[0]->id2ast->is_reg)
+ log_warning("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum);
+ children[0]->was_checked = true;
+ }
break;
case AST_PARAMETER:
@@ -444,7 +465,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, true) == true)
did_something = true;
if (!children[1]->range_valid)
- log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n");
width_hint = max(width_hint, children[1]->range_left - children[1]->range_right + 1);
}
break;
@@ -685,26 +706,47 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
current_scope.clear();
// convert defparam nodes to cell parameters
- if (type == AST_DEFPARAM && !str.empty()) {
- size_t pos = str.rfind('.');
+ if (type == AST_DEFPARAM && !children.empty())
+ {
+ if (children[0]->type != AST_IDENTIFIER)
+ log_file_error(filename, linenum, "Module name in defparam contains non-constant expressions!\n");
+
+ string modname, paramname = children[0]->str;
+
+ size_t pos = paramname.rfind('.');
+
+ while (pos != 0 && pos != std::string::npos)
+ {
+ modname = paramname.substr(0, pos);
+
+ if (current_scope.count(modname))
+ break;
+
+ pos = paramname.rfind('.', pos - 1);
+ }
+
if (pos == std::string::npos)
- log_error("Defparam `%s' does not contain a dot (module/parameter separator) at %s:%d!\n",
- RTLIL::unescape_id(str).c_str(), filename.c_str(), linenum);
- std::string modname = str.substr(0, pos), paraname = "\\" + str.substr(pos+1);
- if (current_scope.count(modname) == 0 || current_scope.at(modname)->type != AST_CELL)
- log_error("Can't find cell for defparam `%s . %s` at %s:%d!\n", RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paraname).c_str(), filename.c_str(), linenum);
- AstNode *cell = current_scope.at(modname), *paraset = clone();
+ log_file_error(filename, linenum, "Can't find object for defparam `%s`!\n", RTLIL::unescape_id(paramname).c_str());
+
+ paramname = "\\" + paramname.substr(pos+1);
+
+ if (current_scope.at(modname)->type != AST_CELL)
+ log_file_error(filename, linenum, "Defparam argument `%s . %s` does not match a cell!\n",
+ RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str());
+
+ AstNode *paraset = new AstNode(AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : NULL);
+ paraset->str = paramname;
+
+ AstNode *cell = current_scope.at(modname);
cell->children.insert(cell->children.begin() + 1, paraset);
- paraset->type = AST_PARASET;
- paraset->str = paraname;
- str.clear();
+ delete_children();
}
// resolve constant prefixes
if (type == AST_PREFIX) {
if (children[0]->type != AST_CONSTANT) {
// dumpAst(NULL, "> ");
- log_error("Index in generate block prefix syntax at %s:%d is not constant!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Index in generate block prefix syntax is not constant!\n");
}
if (children[1]->type == AST_PREFIX)
children[1]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param);
@@ -720,9 +762,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
// evaluate TO_BITS nodes
if (type == AST_TO_BITS) {
if (children[0]->type != AST_CONSTANT)
- log_error("Left operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Left operand of to_bits expression is not constant!\n");
if (children[1]->type != AST_CONSTANT)
- log_error("Right operand of to_bits expression is not constant at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Right operand of to_bits expression is not constant!\n");
RTLIL::Const new_value = children[1]->bitsAsConst(children[0]->bitsAsConst().as_int(), children[1]->is_signed);
newNode = mkconst_bits(new_value.bits, children[1]->is_signed);
goto apply_newNode;
@@ -786,7 +828,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
multirange_dimensions.clear();
for (auto range : children[1]->children) {
if (!range->range_valid)
- log_error("Non-constant range on memory decl at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Non-constant range on memory decl.\n");
multirange_dimensions.push_back(min(range->range_left, range->range_right));
multirange_dimensions.push_back(max(range->range_left, range->range_right) - min(range->range_left, range->range_right) + 1);
total_size *= multirange_dimensions.back();
@@ -804,7 +846,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
for (int i = 0; 2*i < GetSize(id2ast->multirange_dimensions); i++)
{
if (GetSize(children[0]->children) < i)
- log_error("Insufficient number of array indices for %s at %s:%d.\n", log_id(str), filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Insufficient number of array indices for %s.\n", log_id(str));
AstNode *new_index_expr = children[0]->children[i]->children.at(0)->clone();
@@ -833,12 +875,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_PARAMETER || type == AST_LOCALPARAM) {
if (children.size() > 1 && children[1]->type == AST_RANGE) {
if (!children[1]->range_valid)
- log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Non-constant width range on parameter decl.\n");
int width = std::abs(children[1]->range_left - children[1]->range_right) + 1;
if (children[0]->type == AST_REALVALUE) {
RTLIL::Const constvalue = children[0]->realAsConst(width);
- log_warning("converting real value %e to binary %s at %s:%d.\n",
- children[0]->realvalue, log_signal(constvalue), filename.c_str(), linenum);
+ log_file_warning(filename, linenum, "converting real value %e to binary %s.\n",
+ children[0]->realvalue, log_signal(constvalue));
delete children[0];
children[0] = mkconst_bits(constvalue.bits, sign_hint);
did_something = true;
@@ -896,7 +938,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_IDENTIFIER && children.size() == 2 && children[0]->type == AST_RANGE && children[1]->type == AST_RANGE && !in_lvalue)
{
if (id2ast == NULL || id2ast->type != AST_MEMORY || children[0]->children.size() != 1)
- log_error("Invalid bit-select on memory access at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Invalid bit-select on memory access!\n");
int mem_width, mem_size, addr_bits;
id2ast->meminfo(mem_width, mem_size, addr_bits);
@@ -921,6 +963,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
AstNode *assign = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), data);
assign->children[0]->str = wire_id;
+ assign->children[0]->was_checked = true;
if (current_block)
{
@@ -945,10 +988,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
if (type == AST_WHILE)
- log_error("While loops are only allowed in constant functions at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "While loops are only allowed in constant functions!\n");
if (type == AST_REPEAT)
- log_error("Repeat loops are only allowed in constant functions at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Repeat loops are only allowed in constant functions!\n");
// unroll for loops and generate-for blocks
if ((type == AST_GENFOR || type == AST_FOR) && children.size() != 0)
@@ -963,31 +1006,31 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
body_ast = body_ast->children.at(0);
if (init_ast->type != AST_ASSIGN_EQ)
- log_error("Unsupported 1st expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Unsupported 1st expression of generate for-loop!\n");
if (next_ast->type != AST_ASSIGN_EQ)
- log_error("Unsupported 3rd expression of generate for-loop at %s:%d!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Unsupported 3rd expression of generate for-loop!\n");
if (type == AST_GENFOR) {
if (init_ast->children[0]->id2ast == NULL || init_ast->children[0]->id2ast->type != AST_GENVAR)
- log_error("Left hand side of 1st expression of generate for-loop at %s:%d is not a gen var!\n", filename.c_str(), linenum);
+ log_file_error(filename, linenum, "Left hand side of 1st expression of generate for-loop is not a gen var!\n