aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClaire Xen <claire@clairexen.net>2022-02-11 16:03:12 +0100
committerGitHub <noreply@github.com>2022-02-11 16:03:12 +0100
commit49545c73f7f5a5cf73d287fd371f2ff39311f621 (patch)
treed0f20b8def36e551c6735d4fc6033aaa2633fe80
parent90b40aa51f7d666792d4f0b1830ee75b81678a1f (diff)
parente0165188669fcef2c5784c9916683889a2164e5d (diff)
downloadyosys-49545c73f7f5a5cf73d287fd371f2ff39311f621.tar.gz
yosys-49545c73f7f5a5cf73d287fd371f2ff39311f621.tar.bz2
yosys-49545c73f7f5a5cf73d287fd371f2ff39311f621.zip
Merge branch 'master' into clk2ff-better-names
-rw-r--r--.clang-format2
-rw-r--r--.dockerignore3
-rw-r--r--.github/workflows/test-linux.yml125
-rw-r--r--.github/workflows/test-macos.yml154
-rw-r--r--.github/workflows/version.yml34
-rw-r--r--.github/workflows/vs.yml37
-rw-r--r--.mailmap7
-rw-r--r--.travis.yml144
-rwxr-xr-x.travis/build-and-test.sh51
-rw-r--r--.travis/common.sh15
-rwxr-xr-x.travis/deploy-after-success.sh6
-rwxr-xr-x.travis/setup.sh63
-rw-r--r--CHANGELOG258
-rw-r--r--CODEOWNERS5
-rw-r--r--COPYING2
-rw-r--r--Makefile123
-rw-r--r--README.md38
-rw-r--r--backends/aiger/aiger.cc2
-rw-r--r--backends/aiger/xaiger.cc43
-rw-r--r--backends/blif/blif.cc2
-rw-r--r--backends/btor/btor.cc24
-rw-r--r--backends/cxxrtl/cxxrtl.h102
-rw-r--r--backends/cxxrtl/cxxrtl_backend.cc891
-rw-r--r--backends/cxxrtl/cxxrtl_vcd.h15
-rw-r--r--backends/edif/edif.cc2
-rw-r--r--backends/firrtl/firrtl.cc362
-rw-r--r--backends/intersynth/intersynth.cc4
-rw-r--r--backends/json/json.cc44
-rw-r--r--backends/protobuf/Makefile.inc2
-rw-r--r--backends/protobuf/protobuf.cc2
-rw-r--r--backends/rtlil/rtlil_backend.cc51
-rw-r--r--backends/rtlil/rtlil_backend.h2
-rw-r--r--backends/simplec/simplec.cc2
-rw-r--r--backends/smt2/smt2.cc14
-rw-r--r--backends/smt2/smtbmc.py10
-rw-r--r--backends/smt2/smtio.py12
-rw-r--r--backends/smv/smv.cc9
-rw-r--r--backends/spice/spice.cc2
-rw-r--r--backends/table/table.cc2
-rw-r--r--backends/verilog/verilog_backend.cc510
-rw-r--r--examples/smtbmc/Makefile6
-rwxr-xr-xexamples/smtbmc/glift/C7552.v4194
-rw-r--r--examples/smtbmc/glift/C7552.ys41
-rwxr-xr-xexamples/smtbmc/glift/C880.v451
-rw-r--r--examples/smtbmc/glift/C880.ys41
-rwxr-xr-xexamples/smtbmc/glift/alu2.v400
-rw-r--r--examples/smtbmc/glift/alu2.ys41
-rwxr-xr-xexamples/smtbmc/glift/alu4.v802
-rw-r--r--examples/smtbmc/glift/alu4.ys41
-rw-r--r--examples/smtbmc/glift/mux2.ys40
-rwxr-xr-xexamples/smtbmc/glift/t481.v83
-rw-r--r--examples/smtbmc/glift/t481.ys41
-rwxr-xr-xexamples/smtbmc/glift/too_large.v345
-rw-r--r--examples/smtbmc/glift/too_large.ys41
-rwxr-xr-xexamples/smtbmc/glift/ttt2.v220
-rw-r--r--examples/smtbmc/glift/ttt2.ys41
-rwxr-xr-xexamples/smtbmc/glift/x1.v380
-rw-r--r--examples/smtbmc/glift/x1.ys41
-rw-r--r--frontends/aiger/aigerparse.cc2
-rw-r--r--frontends/aiger/aigerparse.h2
-rw-r--r--frontends/ast/Makefile.inc1
-rw-r--r--frontends/ast/ast.cc311
-rw-r--r--frontends/ast/ast.h50
-rw-r--r--frontends/ast/ast_binding.cc49
-rw-r--r--frontends/ast/ast_binding.h58
-rw-r--r--frontends/ast/dpicall.cc2
-rw-r--r--frontends/ast/genrtlil.cc268
-rw-r--r--frontends/ast/simplify.cc688
-rw-r--r--frontends/blif/blifparse.cc39
-rw-r--r--frontends/blif/blifparse.h2
-rw-r--r--frontends/json/jsonparse.cc52
-rw-r--r--frontends/liberty/liberty.cc2
-rw-r--r--frontends/rtlil/rtlil_frontend.cc2
-rw-r--r--frontends/rtlil/rtlil_frontend.h2
-rw-r--r--frontends/rtlil/rtlil_lexer.l3
-rw-r--r--frontends/rtlil/rtlil_parser.y27
-rw-r--r--frontends/verific/Makefile.inc2
-rw-r--r--frontends/verific/README8
-rw-r--r--frontends/verific/verific.cc521
-rw-r--r--frontends/verific/verific.h3
-rw-r--r--frontends/verific/verificsva.cc2
-rw-r--r--frontends/verilog/const2ast.cc2
-rw-r--r--frontends/verilog/preproc.cc66
-rw-r--r--frontends/verilog/preproc.h3
-rw-r--r--frontends/verilog/verilog_frontend.cc21
-rw-r--r--frontends/verilog/verilog_frontend.h4
-rw-r--r--frontends/verilog/verilog_lexer.l52
-rw-r--r--frontends/verilog/verilog_parser.y499
-rw-r--r--guidelines/Checklists120
-rw-r--r--guidelines/CodeOfConduct (renamed from CodeOfConduct)5
-rw-r--r--guidelines/CodingStyle35
-rw-r--r--guidelines/GettingStarted (renamed from CodingReadme)309
-rw-r--r--guidelines/UnitTests69
-rw-r--r--guidelines/Windows83
-rw-r--r--kernel/binding.cc29
-rw-r--r--kernel/binding.h60
-rw-r--r--kernel/bitpattern.h2
-rw-r--r--kernel/calc.cc53
-rw-r--r--kernel/cellaigs.cc2
-rw-r--r--kernel/cellaigs.h2
-rw-r--r--kernel/celledges.cc42
-rw-r--r--kernel/celledges.h2
-rw-r--r--kernel/celltypes.h46
-rw-r--r--kernel/consteval.h37
-rw-r--r--kernel/constids.inc22
-rw-r--r--kernel/cost.h2
-rw-r--r--kernel/driver.cc42
-rw-r--r--kernel/ff.cc755
-rw-r--r--kernel/ff.h534
-rw-r--r--kernel/ffinit.h1
-rw-r--r--kernel/ffmerge.cc359
-rw-r--r--kernel/ffmerge.h141
-rw-r--r--kernel/fstdata.cc252
-rw-r--r--kernel/fstdata.h81
-rw-r--r--kernel/hashlib.h8
-rw-r--r--kernel/log.cc24
-rw-r--r--kernel/log.h28
-rw-r--r--kernel/macc.h2
-rw-r--r--kernel/mem.cc1386
-rw-r--r--kernel/mem.h185
-rw-r--r--kernel/modtools.h10
-rw-r--r--kernel/qcsat.cc102
-rw-r--r--kernel/qcsat.h76
-rw-r--r--kernel/register.cc2
-rw-r--r--kernel/register.h2
-rw-r--r--kernel/rtlil.cc481
-rw-r--r--kernel/rtlil.h99
-rw-r--r--kernel/satgen.cc122
-rw-r--r--kernel/satgen.h2
-rw-r--r--kernel/sigtools.h2
-rw-r--r--kernel/timinginfo.h50
-rw-r--r--kernel/utils.h2
-rw-r--r--kernel/yosys.cc43
-rw-r--r--kernel/yosys.h14
-rw-r--r--libs/bigint/README2
-rw-r--r--libs/ezsat/README2
-rw-r--r--libs/ezsat/demo_bit.cc2
-rw-r--r--libs/ezsat/demo_cmp.cc2
-rw-r--r--libs/ezsat/demo_vec.cc2
-rw-r--r--libs/ezsat/ezminisat.cc2
-rw-r--r--libs/ezsat/ezminisat.h2
-rw-r--r--libs/ezsat/ezsat.cc2
-rw-r--r--libs/ezsat/ezsat.h2
-rw-r--r--libs/ezsat/puzzle3d.cc2
-rw-r--r--libs/ezsat/testbench.cc2
-rw-r--r--libs/fst/block_format.txt130
-rw-r--r--libs/fst/config.h27
-rw-r--r--libs/fst/fastlz.cc528
-rw-r--r--libs/fst/fastlz.h109
-rw-r--r--libs/fst/fstapi.cc6546
-rw-r--r--libs/fst/fstapi.h500
-rw-r--r--libs/fst/lz4.cc1615
-rw-r--r--libs/fst/lz4.h367
-rw-r--r--libs/subcircuit/README2
-rw-r--r--libs/subcircuit/subcircuit.cc2
-rw-r--r--libs/subcircuit/subcircuit.h2
-rw-r--r--manual/APPNOTE_010_Verilog_to_BLIF.tex8
-rw-r--r--manual/APPNOTE_011_Design_Investigation.tex6
-rw-r--r--manual/APPNOTE_012_Verilog_to_BTOR.tex6
-rw-r--r--manual/CHAPTER_Auxlibs.tex4
-rw-r--r--manual/CHAPTER_CellLib.tex148
-rw-r--r--manual/CHAPTER_Overview.tex5
-rw-r--r--manual/CHAPTER_Prog.tex11
-rw-r--r--manual/CHAPTER_StateOfTheArt/simlib_yosys.v2
-rw-r--r--manual/CHAPTER_TextRtlil.tex2
-rw-r--r--manual/CHAPTER_Verilog.tex5
-rw-r--r--manual/PRESENTATION_ExAdv.tex2
-rw-r--r--manual/PRESENTATION_ExOth.tex2
-rw-r--r--manual/PRESENTATION_ExSyn.tex2
-rw-r--r--manual/PRESENTATION_Intro.tex14
-rw-r--r--manual/PRESENTATION_Prog.tex2
-rw-r--r--manual/PRESENTATION_Prog/Makefile2
-rw-r--r--manual/command-reference-manual.tex2073
-rw-r--r--manual/literature.bib8
-rw-r--r--manual/manual.tex4
-rw-r--r--manual/presentation.tex6
-rw-r--r--manual/weblinks.bib12
-rw-r--r--misc/create_vcxsrc.sh15
-rw-r--r--misc/py_wrap_generator.py6
-rw-r--r--passes/cmds/Makefile.inc3
-rw-r--r--passes/cmds/add.cc2
-rw-r--r--passes/cmds/autoname.cc28
-rw-r--r--passes/cmds/blackbox.cc5
-rw-r--r--passes/cmds/bugpoint.cc53
-rw-r--r--passes/cmds/check.cc10
-rw-r--r--passes/cmds/chformal.cc2
-rw-r--r--passes/cmds/chtype.cc2
-rw-r--r--passes/cmds/clean_zerowidth.cc210
-rw-r--r--passes/cmds/connect.cc30
-rw-r--r--passes/cmds/connwrappers.cc2
-rw-r--r--passes/cmds/copy.cc2
-rw-r--r--passes/cmds/cover.cc2
-rw-r--r--passes/cmds/delete.cc14
-rw-r--r--passes/cmds/design.cc2
-rw-r--r--passes/cmds/edgetypes.cc2
-rw-r--r--passes/cmds/exec.cc2
-rw-r--r--passes/cmds/glift.cc599
-rw-r--r--passes/cmds/logcmd.cc2
-rw-r--r--passes/cmds/logger.cc11
-rw-r--r--passes/cmds/ltp.cc2
-rw-r--r--passes/cmds/plugin.cc2
-rw-r--r--passes/cmds/portlist.cc2
-rw-r--r--passes/cmds/qwp.cc2
-rw-r--r--passes/cmds/rename.cc2
-rw-r--r--passes/cmds/scatter.cc2
-rw-r--r--passes/cmds/scc.cc2
-rw-r--r--passes/cmds/scratchpad.cc4
-rw-r--r--passes/cmds/select.cc2
-rw-r--r--passes/cmds/setattr.cc2
-rw-r--r--passes/cmds/setundef.cc2
-rw-r--r--passes/cmds/show.cc26
-rw-r--r--passes/cmds/splice.cc2
-rw-r--r--passes/cmds/splitnets.cc2
-rw-r--r--passes/cmds/sta.cc312
-rw-r--r--passes/cmds/stat.cc8
-rw-r--r--passes/cmds/tee.cc2
-rw-r--r--passes/cmds/torder.cc4
-rw-r--r--passes/cmds/trace.cc2
-rw-r--r--passes/cmds/write_file.cc2
-rw-r--r--passes/equiv/equiv_add.cc2
-rw-r--r--passes/equiv/equiv_induct.cc7
-rw-r--r--passes/equiv/equiv_make.cc2
-rw-r--r--passes/equiv/equiv_mark.cc2
-rw-r--r--passes/equiv/equiv_miter.cc2
-rw-r--r--passes/equiv/equiv_purge.cc2
-rw-r--r--passes/equiv/equiv_remove.cc2
-rw-r--r--passes/equiv/equiv_simple.cc10
-rw-r--r--passes/equiv/equiv_status.cc2
-rw-r--r--passes/equiv/equiv_struct.cc2
-rw-r--r--passes/fsm/fsm.cc2
-rw-r--r--passes/fsm/fsm_detect.cc2
-rw-r--r--passes/fsm/fsm_expand.cc2
-rw-r--r--passes/fsm/fsm_export.cc2
-rw-r--r--passes/fsm/fsm_extract.cc2
-rw-r--r--passes/fsm/fsm_info.cc2
-rw-r--r--passes/fsm/fsm_map.cc2
-rw-r--r--passes/fsm/fsm_opt.cc2
-rw-r--r--passes/fsm/fsm_recode.cc2
-rw-r--r--passes/fsm/fsmdata.h2
-rw-r--r--passes/hierarchy/hierarchy.cc489
-rw-r--r--passes/hierarchy/submod.cc2
-rw-r--r--passes/hierarchy/uniquify.cc2
-rw-r--r--passes/memory/Makefile.inc1
-rw-r--r--passes/memory/memory.cc30
-rw-r--r--passes/memory/memory_bram.cc461
-rw-r--r--passes/memory/memory_collect.cc2
-rw-r--r--passes/memory/memory_dff.cc862
-rw-r--r--passes/memory/memory_map.cc95
-rw-r--r--passes/memory/memory_memx.cc75
-rw-r--r--passes/memory/memory_narrow.cc67
-rw-r--r--passes/memory/memory_nordff.cc25
-rw-r--r--passes/memory/memory_share.cc959
-rw-r--r--passes/memory/memory_unpack.cc2
-rw-r--r--passes/opt/Makefile.inc3
-rw-r--r--passes/opt/muxpack.cc2
-rw-r--r--passes/opt/opt.cc2
-rw-r--r--passes/opt/opt_clean.cc34
-rw-r--r--passes/opt/opt_demorgan.cc2
-rw-r--r--passes/opt/opt_dff.cc421
-rw-r--r--passes/opt/opt_expr.cc248
-rw-r--r--passes/opt/opt_lut.cc53
-rw-r--r--passes/opt/opt_lut_ins.cc12
-rw-r--r--passes/opt/opt_mem.cc26
-rw-r--r--passes/opt/opt_mem_feedback.cc350
-rw-r--r--passes/opt/opt_mem_priority.cc109
-rw-r--r--passes/opt/opt_mem_widen.cc107
-rw-r--r--passes/opt/opt_merge.cc40
-rw-r--r--passes/opt/opt_muxtree.cc35
-rw-r--r--passes/opt/opt_reduce.cc403
-rw-r--r--passes/opt/opt_share.cc2
-rw-r--r--passes/opt/pmux2shiftx.cc2
-rw-r--r--passes/opt/rmports.cc2
-rw-r--r--passes/opt/share.cc86
-rw-r--r--passes/opt/wreduce.cc4
-rw-r--r--passes/pmgen/Makefile.inc9
-rw-r--r--passes/pmgen/generate.h2
-rw-r--r--passes/pmgen/ice40_dsp.cc2
-rw-r--r--passes/pmgen/ice40_dsp.pmg5
-rw-r--r--passes/pmgen/ice40_wrapcarry.cc2
-rw-r--r--passes/pmgen/peepopt.cc2
-rw-r--r--passes/pmgen/test_pmgen.cc2
-rw-r--r--passes/pmgen/xilinx_dsp.cc2
-rw-r--r--passes/pmgen/xilinx_srl.cc2
-rw-r--r--passes/proc/Makefile.inc1
-rw-r--r--passes/proc/proc.cc15
-rw-r--r--passes/proc/proc_arst.cc110
-rw-r--r--passes/proc/proc_clean.cc44
-rw-r--r--passes/proc/proc_dff.cc45
-rw-r--r--passes/proc/proc_dlatch.cc9
-rw-r--r--passes/proc/proc_init.cc16
-rw-r--r--passes/proc/proc_memwr.cc121
-rw-r--r--passes/proc/proc_mux.cc2
-rw-r--r--passes/proc/proc_prune.cc65
-rw-r--r--passes/proc/proc_rmdead.cc67
-rw-r--r--passes/sat/assertpmux.cc2
-rw-r--r--passes/sat/async2sync.cc72
-rw-r--r--passes/sat/clk2fflogic.cc56
-rw-r--r--passes/sat/cutpoint.cc2
-rw-r--r--passes/sat/eval.cc4
-rw-r--r--passes/sat/expose.cc2
-rw-r--r--passes/sat/fmcombine.cc2
-rw-r--r--passes/sat/fminit.cc2
-rw-r--r--passes/sat/freduce.cc2
-rw-r--r--passes/sat/miter.cc2
-rw-r--r--passes/sat/mutate.cc2
-rw-r--r--passes/sat/sat.cc2
-rw-r--r--passes/sat/sim.cc470
-rw-r--r--passes/sat/supercover.cc2
-rw-r--r--passes/techmap/Makefile.inc2
-rw-r--r--passes/techmap/abc.cc63
-rw-r--r--passes/techmap/abc9.cc24
-rw-r--r--passes/techmap/abc9_exe.cc2
-rw-r--r--passes/techmap/abc9_ops.cc183
-rw-r--r--passes/techmap/aigmap.cc2
-rw-r--r--passes/techmap/alumacc.cc2
-rw-r--r--passes/techmap/attrmap.cc2
-rw-r--r--passes/techmap/attrmvcp.cc2
-rw-r--r--passes/techmap/bmuxmap.cc76
-rw-r--r--passes/techmap/clkbufmap.cc2
-rw-r--r--passes/techmap/deminout.cc2
-rw-r--r--passes/techmap/demuxmap.cc80
-rw-r--r--passes/techmap/dffinit.cc2
-rw-r--r--passes/techmap/dfflegalize.cc1866
-rw-r--r--passes/techmap/dfflibmap.cc2
-rw-r--r--passes/techmap/dffunmap.cc13
-rw-r--r--passes/techmap/extract.cc3
-rw-r--r--passes/techmap/extract_counter.cc2
-rw-r--r--passes/techmap/extract_fa.cc4
-rw-r--r--passes/techmap/extract_reduce.cc107
-rw-r--r--passes/techmap/extractinv.cc2
-rw-r--r--passes/techmap/flatten.cc16
-rw-r--r--passes/techmap/hilomap.cc2
-rw-r--r--passes/techmap/insbuf.cc2
-rw-r--r--passes/techmap/iopadmap.cc33
-rw-r--r--passes/techmap/libparse.cc6
-rw-r--r--passes/techmap/libparse.h2
-rw-r--r--passes/techmap/lut2mux.cc2
-rw-r--r--passes/techmap/maccmap.cc2
-rw-r--r--passes/techmap/muxcover.cc2
-rw-r--r--passes/techmap/nlutmap.cc2
-rw-r--r--passes/techmap/pmuxtree.cc2
-rw-r--r--passes/techmap/shregmap.cc2
-rw-r--r--passes/techmap/simplemap.cc334
-rw-r--r--passes/techmap/simplemap.h9
-rw-r--r--passes/techmap/techmap.cc12
-rw-r--r--passes/techmap/tribuf.cc2
-rw-r--r--passes/techmap/zinit.cc125
-rw-r--r--passes/tests/test_abcloop.cc2
-rw-r--r--passes/tests/test_autotb.cc2
-rw-r--r--passes/tests/test_cell.cc48
-rw-r--r--techlibs/achronix/speedster22i/cells_arith.v2
-rw-r--r--techlibs/achronix/speedster22i/cells_map.v2
-rw-r--r--techlibs/achronix/speedster22i/cells_sim.v2
-rw-r--r--techlibs/achronix/synth_achronix.cc3
-rw-r--r--techlibs/anlogic/.gitignore2
-rw-r--r--techlibs/anlogic/Makefile.inc22
-rw-r--r--techlibs/anlogic/anlogic_eqn.cc2
-rw-r--r--techlibs/anlogic/anlogic_fixcarry.cc2
-rw-r--r--techlibs/anlogic/arith_map.v4
-rw-r--r--techlibs/anlogic/brams.txt43
-rw-r--r--techlibs/anlogic/brams_init.py21
-rw-r--r--techlibs/anlogic/brams_map.v162
-rw-r--r--techlibs/anlogic/synth_anlogic.cc23
-rw-r--r--techlibs/common/abc9_model.v4
-rw-r--r--techlibs/common/abc9_unmap.v5
-rw-r--r--techlibs/common/gen_fine_ffs.py49
-rw-r--r--techlibs/common/mul2dsp.v636
-rw-r--r--techlibs/common/prep.cc15
-rw-r--r--techlibs/common/simcells.v286
-rw-r--r--techlibs/common/simlib.v316
-rw-r--r--techlibs/common/synth.cc2
-rw-r--r--techlibs/common/techmap.v43
-rw-r--r--techlibs/coolrunner2/synth_coolrunner2.cc1
-rw-r--r--techlibs/easic/synth_easic.cc3
-rw-r--r--techlibs/ecp5/arith_map.v4
-rw-r--r--techlibs/ecp5/brams.txt2
-rw-r--r--techlibs/ecp5/cells_bb.v41
-rw-r--r--techlibs/ecp5/cells_map.v13
-rw-r--r--techlibs/ecp5/cells_sim.v2
-rw-r--r--techlibs/ecp5/ecp5_gsr.cc4
-rw-r--r--techlibs/ecp5/lutrams.txt2
-rw-r--r--techlibs/ecp5/synth_ecp5.cc20
-rw-r--r--techlibs/efinix/arith_map.v4
-rw-r--r--techlibs/efinix/efinix_fixcarry.cc2
-rw-r--r--techlibs/efinix/synth_efinix.cc5
-rw-r--r--techlibs/gatemate/Makefile.inc14
-rw-r--r--techlibs/gatemate/arith_map.v69
-rw-r--r--techlibs/gatemate/brams.txt280
-rw-r--r--techlibs/gatemate/brams_init_20.vh64
-rw-r--r--techlibs/gatemate/brams_init_40.vh260
-rw-r--r--techlibs/gatemate/brams_map.v520
-rw-r--r--techlibs/gatemate/cells_bb.v191
-rw-r--r--techlibs/gatemate/cells_sim.v1411
-rw-r--r--techlibs/gatemate/lut_map.v45
-rw-r--r--techlibs/gatemate/mul_map.v77
-rw-r--r--techlibs/gatemate/mux_map.v56
-rw-r--r--techlibs/gatemate/reg_map.v45
-rw-r--r--techlibs/gatemate/synth_gatemate.cc351
-rw-r--r--techlibs/gowin/arith_map.v4
-rw-r--r--techlibs/gowin/cells_map.v1
-rw-r--r--techlibs/gowin/cells_sim.v281
-rw-r--r--techlibs/gowin/lutrams_map.v5
-rw-r--r--techlibs/gowin/synth_gowin.cc16
-rw-r--r--techlibs/greenpak4/greenpak4_dffinv.cc2
-rw-r--r--techlibs/greenpak4/synth_greenpak4.cc3
-rw-r--r--techlibs/ice40/abc9_model.v42
-rw-r--r--techlibs/ice40/arith_map.v2
-rw-r--r--techlibs/ice40/cells_sim.v1164
-rw-r--r--techlibs/ice40/ice40_braminit.cc2
-rw-r--r--techlibs/ice40/ice40_opt.cc2
-rw-r--r--techlibs/ice40/synth_ice40.cc5
-rw-r--r--techlibs/intel/common/altpll_bb.v2
-rw-r--r--techlibs/intel/common/m9k_bb.v2
-rw-r--r--techlibs/intel/cyclone10lp/cells_arith.v2
-rw-r--r--techlibs/intel/cyclone10lp/cells_map.v2
-rw-r--r--techlibs/intel/cyclone10lp/cells_sim.v2
-rw-r--r--techlibs/intel/cycloneiv/cells_arith.v2
-rw-r--r--techlibs/intel/cycloneiv/cells_map.v2
-rw-r--r--techlibs/intel/cycloneiv/cells_sim.v2
-rw-r--r--techlibs/intel/cycloneive/arith_map.v2
-rw-r--r--techlibs/intel/cycloneive/cells_map.v2
-rw-r--r--techlibs/intel/cycloneive/cells_sim.v2
-rw-r--r--techlibs/intel/max10/cells_arith.v2
-rw-r--r--techlibs/intel/max10/cells_map.v2
-rw-r--r--techlibs/intel/max10/cells_sim.v2
-rw-r--r--techlibs/intel/synth_intel.cc3
-rw-r--r--techlibs/intel_alm/Makefile.inc1
-rw-r--r--techlibs/intel_alm/common/alm_sim.v76
-rw-r--r--techlibs/intel_alm/common/arith_alm_map.v2
-rw-r--r--techlibs/intel_alm/common/bram_m10k.txt12
-rw-r--r--techlibs/intel_alm/common/bram_m20k_map.v62
-rw-r--r--techlibs/intel_alm/common/dff_sim.v19
-rw-r--r--techlibs/intel_alm/common/dsp_sim.v47
-rw-r--r--techlibs/intel_alm/common/megafunction_bb.v88
-rw-r--r--techlibs/intel_alm/common/mem_sim.v56
-rw-r--r--techlibs/intel_alm/common/misc_sim.v21
-rw-r--r--techlibs/intel_alm/common/quartus_rename.v73
-rw-r--r--techlibs/intel_alm/cyclonev/cells_sim.v30
-rw-r--r--techlibs/intel_alm/synth_intel_alm.cc38
-rw-r--r--techlibs/machxo2/cells_map.v4
-rw-r--r--techlibs/machxo2/cells_sim.v4
-rw-r--r--techlibs/machxo2/synth_machxo2.cc3
-rw-r--r--techlibs/nexus/arith_map.v6
-rw-r--r--techlibs/nexus/cells_map.v8
-rw-r--r--techlibs/nexus/cells_sim.v4
-rw-r--r--techlibs/nexus/synth_nexus.cc5
-rw-r--r--techlibs/quicklogic/Makefile.inc13
-rw-r--r--techlibs/quicklogic/abc9_map.v26
-rw-r--r--techlibs/quicklogic/abc9_model.v11
-rw-r--r--techlibs/quicklogic/abc9_unmap.v14
-rw-r--r--techlibs/quicklogic/cells_sim.v36
-rw-r--r--techlibs/quicklogic/lut_sim.v76
-rw-r--r--techlibs/quicklogic/pp3_cells_map.v36
-rw-r--r--techlibs/quicklogic/pp3_cells_sim.v329
-rw-r--r--techlibs/quicklogic/pp3_ffs_map.v4
-rw-r--r--techlibs/quicklogic/pp3_latches_map.v11
-rw-r--r--techlibs/quicklogic/pp3_lut_map.v53
-rw-r--r--techlibs/quicklogic/synth_quicklogic.cc236
-rw-r--r--techlibs/sf2/arith_map.v2
-rw-r--r--techlibs/sf2/cells_sim.v6
-rw-r--r--techlibs/sf2/synth_sf2.cc3
-rw-r--r--techlibs/xilinx/abc9_model.v2
-rw-r--r--techlibs/xilinx/arith_map.v2
-rw-r--r--techlibs/xilinx/cells_map.v10
-rw-r--r--techlibs/xilinx/cells_sim.v2
-rw-r--r--techlibs/xilinx/ff_map.v2
-rw-r--r--techlibs/xilinx/lut_map.v2
-rw-r--r--techlibs/xilinx/mux_map.v2
-rw-r--r--techlibs/xilinx/synth_xilinx.cc10
-rw-r--r--techlibs/xilinx/xc7_brams_map.v10
-rw-r--r--techlibs/xilinx/xilinx_dffopt.cc2
-rw-r--r--tests/arch/anlogic/blockram.ys13
-rw-r--r--tests/arch/anlogic/lutram.ys11
-rw-r--r--tests/arch/common/adffs.v8
-rw-r--r--tests/arch/common/counter.v22
-rw-r--r--tests/arch/common/dffs.v2
-rw-r--r--tests/arch/common/fsm.v102
-rw-r--r--tests/arch/common/shifter.v28
-rw-r--r--tests/arch/ecp5/bug2731.ys7
-rw-r--r--tests/arch/ecp5/lutram.ys8
-rw-r--r--tests/arch/ecp5/memories.ys187
-rw-r--r--tests/arch/ecp5/mux.ys18
-rw-r--r--tests/arch/gatemate/.gitignore4
-rw-r--r--tests/arch/gatemate/add_sub.ys9
-rw-r--r--tests/arch/gatemate/adffs.ys43
-rw-r--r--tests/arch/gatemate/counter.ys12
-rw-r--r--tests/arch/gatemate/dffs.ys21
-rw-r--r--tests/arch/gatemate/fsm.ys20
-rw-r--r--tests/arch/gatemate/latches.ys29
-rw-r--r--tests/arch/gatemate/logic.ys10
-rw-r--r--tests/arch/gatemate/memory.ys34
-rw-r--r--tests/arch/gatemate/mul.v79
-rw-r--r--tests/arch/gatemate/mul.ys33
-rw-r--r--tests/arch/gatemate/mux.ys24
-rwxr-xr-xtests/arch/gatemate/run-test.sh4
-rw-r--r--tests/arch/gatemate/shifter.ys10
-rw-r--r--tests/arch/gatemate/tribuf.ys13
-rw-r--r--tests/arch/gowin/lutram.ys5
-rw-r--r--tests/arch/gowin/tribuf.ys3
-rw-r--r--tests/arch/ice40/bug2061.ys24
-rw-r--r--tests/arch/ice40/memories.ys97
-rw-r--r--tests/arch/intel_alm/add_sub.ys8
-rw-r--r--tests/arch/intel_alm/adffs.ys16
-rw-r--r--tests/arch/intel_alm/blockram.ys2
-rw-r--r--tests/arch/intel_alm/counter.ys8
-rw-r--r--tests/arch/intel_alm/dffs.ys8
-rw-r--r--tests/arch/intel_alm/fsm.ys4
-rw-r--r--tests/arch/intel_alm/logic.ys4
-rw-r--r--tests/arch/intel_alm/lutram.ys14
-rw-r--r--tests/arch/intel_alm/mul.ys10
-rw-r--r--tests/arch/intel_alm/mux.ys16
-rw-r--r--tests/arch/intel_alm/quartus_ice.ys2
-rw-r--r--tests/arch/intel_alm/shifter.ys4
-rw-r--r--tests/arch/intel_alm/tribuf.ys4
-rw-r--r--tests/arch/machxo2/mux.ys2
-rw-r--r--tests/arch/machxo2/tribuf.ys4
-rw-r--r--tests/arch/nexus/lutram.ys4
-rw-r--r--tests/arch/quicklogic/.gitignore4
-rw-r--r--tests/arch/quicklogic/add_sub.ys11
-rw-r--r--tests/arch/quicklogic/adffs.ys67
-rw-r--r--tests/arch/quicklogic/counter.ys18
-rw-r--r--tests/arch/quicklogic/dffs.ys20
-rw-r--r--tests/arch/quicklogic/fsm.ys23
-rw-r--r--tests/arch/quicklogic/latches.ys40
-rw-r--r--tests/arch/quicklogic/logic.ys14
-rw-r--r--tests/arch/quicklogic/mux.ys52
-rwxr-xr-xtests/arch/quicklogic/run-test.sh4
-rw-r--r--tests/arch/quicklogic/tribuf.ys13
-rwxr-xr-xtests/arch/run-test.sh2
-rw-r--r--tests/arch/xilinx/abc9_dff.ys6
-rw-r--r--tests/arch/xilinx/fsm.ys5
-rw-r--r--tests/arch/xilinx/tribuf.sh4
-rw-r--r--tests/bind/.gitignore2
-rw-r--r--tests/bind/basic.sv20
-rw-r--r--tests/bind/basic.ys1
-rw-r--r--tests/bind/cell_list.sv26
-rw-r--r--tests/bind/cell_list.ys1
-rw-r--r--tests/bind/hier.sv20
-rw-r--r--tests/bind/hier.ys1
-rw-r--r--tests/bind/inst_list.sv24
-rw-r--r--tests/bind/inst_list.ys1
-rw-r--r--tests/bind/param.sv26
-rw-r--r--tests/bind/param.ys1
-rwxr-xr-xtests/bind/run-test.sh20
-rw-r--r--tests/bind/toplevel.sv20
-rw-r--r--tests/bind/toplevel.ys1
-rw-r--r--tests/blif/.gitignore1
-rw-r--r--tests/blif/bug2729.ys20
-rwxr-xr-xtests/blif/run-test.sh6
-rw-r--r--tests/bram/generate.py28
-rw-r--r--tests/bram/run-single.sh2
-rw-r--r--tests/memories/read_arst.v27
-rw-r--r--tests/memories/read_two_mux.v5
-rwxr-xr-xtests/memories/run-test.sh34
-rw-r--r--tests/memories/trans_addr_enable.v21
-rw-r--r--tests/memories/trans_sdp.v21
-rw-r--r--tests/memories/trans_sp.v21
-rw-r--r--tests/memories/wide_all.v36
-rw-r--r--tests/memories/wide_read_async.v27
-rw-r--r--tests/memories/wide_read_mixed.v46
-rw-r--r--tests/memories/wide_read_sync.v32
-rw-r--r--tests/memories/wide_read_trans.v40
-rw-r--r--tests/memories/wide_thru_priority.v29
-rw-r--r--tests/memories/wide_write.v29
-rw-r--r--tests/opt/bug1854.ys17
-rw-r--r--tests/opt/bug2623.ys14
-rw-r--r--tests/opt/bug2765.ys34
-rw-r--r--tests/opt/bug2766.ys101
-rw-r--r--tests/opt/bug2824.ys7
-rw-r--r--tests/opt/bug2920.ys42
-rw-r--r--tests/opt/bug3047.ys12
-rw-r--r--tests/opt/bug3117.ys34
-rw-r--r--tests/opt/memory_dff_trans.ys874
-rw-r--r--tests/opt/memory_map_offset.ys100
-rw-r--r--tests/opt/opt_clean_init.ys31
-rw-r--r--tests/opt/opt_clean_mem.ys17
-rw-r--r--tests/opt/opt_dff_sr.ys21
-rw-r--r--tests/opt/opt_expr_constconn.v8
-rw-r--r--tests/opt/opt_expr_constconn.ys7
-rw-r--r--tests/opt/opt_mem_feedback.ys189
-rw-r--r--tests/opt/opt_mem_priority.ys209
-rw-r--r--tests/opt/opt_merge_init.ys2
-rw-r--r--tests/opt/opt_reduce_bmux.ys117
-rw-r--r--tests/opt/opt_reduce_demux.ys91
-rw-r--r--tests/proc/bug2619.ys23
-rw-r--r--tests/proc/bug2656.ys31
-rw-r--r--tests/proc/bug2962.ys22
-rw-r--r--tests/proc/rmdead.v46
-rw-r--r--tests/proc/rmdead.ys4
-rw-r--r--tests/sat/.gitignore2
-rw-r--r--tests/sat/alu.v79
-rw-r--r--tests/sat/grom.ys9
-rw-r--r--tests/sat/grom_computer.v31
-rw-r--r--tests/sat/grom_cpu.v747
-rw-r--r--tests/sat/ram_memory.v37
-rw-r--r--tests/sat/sim_counter.ys48
-rw-r--r--tests/simple/asgn_binop.sv23
-rw-r--r--tests/simple/attrib01_module.v6
-rw-r--r--tests/simple/attrib02_port_decl.v6
-rw-r--r--tests/simple/attrib03_parameter.v6
-rw-r--r--tests/simple/attrib04_net_var.v6
-rw-r--r--tests/simple/attrib05_port_conn.v.DISABLED6
-rw-r--r--tests/simple/attrib06_operator_suffix.v6
-rw-r--r--tests/simple/attrib07_func_call.v.DISABLED6
-rw-r--r--tests/simple/attrib08_mod_inst.v6
-rw-r--r--tests/simple/attrib09_case.v6
-rw-r--r--tests/simple/case_expr_const.v49
-rw-r--r--tests/simple/case_expr_extend.sv11
-rw-r--r--tests/simple/case_expr_non_const.v59
-rw-r--r--tests/simple/case_expr_query.sv32
-rw-r--r--tests/simple/case_large.v273
-rw-r--r--tests/simple/const_branch_finish.v2
-rw-r--r--tests/simple/const_fold_func.v2
-rw-r--r--tests/simple/const_func_shadow.v2
-rw-r--r--tests/simple/defvalue.sv2
-rw-r--r--tests/simple/func_block.v2
-rw-r--r--tests/simple/func_recurse.v2
-rw-r--r--tests/simple/func_width_scope.v2
-rw-r--r--tests/simple/genblk_collide.v4
-rw-r--r--tests/simple/genblk_dive.v2
-rw-r--r--tests/simple/genblk_order.v2
-rw-r--r--tests/simple/genblk_port_shadow.v2
-rw-r--r--tests/simple/hierarchy.v2
-rw-r--r--tests/simple/ifdef_1.v2
-rw-r--r--tests/simple/ifdef_2.v2
-rw-r--r--tests/simple/lesser_size_cast.sv7
-rw-r--r--tests/simple/local_loop_var.sv2
-rw-r--r--tests/simple/loop_prefix_case.v18
-rw-r--r--tests/simple/loop_var_shadow.v2
-rw-r--r--tests/simple/macro_arg_spaces.sv2
-rw-r--r--tests/simple/macro_arg_surrounding_spaces.v2
-rw-r--r--tests/simple/matching_end_labels.sv29
-rw-r--r--tests/simple/mem2reg_bounds_tern.v19
-rw-r--r--tests/simple/memwr_port_connection.sv13
-rw-r--r--tests/simple/module_scope.v29
-rw-r--r--tests/simple/module_scope_case.v11
-rw-r--r--tests/simple/named_genblk.v2
-rw-r--r--tests/simple/nested_genblk_resolve.v2
-rw-r--r--tests/simple/signed_full_slice.v29
-rw-r--r--tests/simple/string_format.v2
-rw-r--r--tests/simple/unnamed_block_decl.sv2
-rw-r--r--tests/simple/verilog_primitives.v15
-rw-r--r--tests/simple/vloghammer.v2
-rw-r--r--tests/simple/wandwor.v12
-rw-r--r--tests/simple_abc9/abc9.box3
-rw-r--r--tests/simple_abc9/abc9.v24
-rwxr-xr-xtests/simple_abc9/run-test.sh12
-rw-r--r--tests/svinterfaces/load_and_derive.sv20
-rw-r--r--tests/svinterfaces/load_and_derive.ys6
-rw-r--r--tests/svinterfaces/ondemand.sv5
-rwxr-xr-xtests/svinterfaces/run-test.sh4
-rwxr-xr-xtests/svinterfaces/run_simple.sh15
-rw-r--r--tests/svtypes/logic_rom.ys2
-rw-r--r--tests/svtypes/typedef_initial_and_assign.sv94
-rw-r--r--tests/svtypes/typedef_initial_and_assign.ys14
-rw-r--r--tests/svtypes/typedef_memory.ys2
-rw-r--r--tests/svtypes/typedef_memory_2.ys2
-rw-r--r--tests/svtypes/typedef_scopes.sv10
-rw-r--r--tests/techmap/bug2759.ys14
-rw-r--r--tests/techmap/bug2972.ys20
-rw-r--r--tests/techmap/dfflegalize_adff.ys32
-rw-r--r--tests/techmap/dfflegalize_adff_init.ys84
-rw-r--r--tests/techmap/dfflegalize_adlatch_init.ys4
-rw-r--r--tests/techmap/dfflegalize_aldff.ys92
-rw-r--r--tests/techmap/dfflegalize_aldff_init.ys148
-rw-r--r--tests/techmap/dfflegalize_dff.ys69
-rw-r--r--tests/techmap/dfflegalize_dff_init.ys138
-rw-r--r--tests/techmap/dfflegalize_dlatch.ys22
-rw-r--r--tests/techmap/dfflegalize_dlatch_const.ys8
-rw-r--r--tests/techmap/dfflegalize_dlatch_init.ys38
-rw-r--r--tests/techmap/dfflegalize_dlatchsr_init.ys8
-rw-r--r--tests/techmap/dfflegalize_inv.ys27
-rw-r--r--tests/techmap/dfflegalize_minsrst.ys4
-rw-r--r--tests/techmap/dfflegalize_sr.ys2
-rw-r--r--tests/techmap/dfflegalize_sr_init.ys10
-rw-r--r--tests/techmap/iopadmap.ys4
-rw-r--r--tests/techmap/mem_simple_4x1_runtest.sh2
-rw-r--r--tests/techmap/recursive_runtest.sh2
-rw-r--r--tests/techmap/zinit.ys7
-rwxr-xr-xtests/tools/autotest.sh2
-rwxr-xr-xtests/tools/vcdcd.pl6
-rw-r--r--tests/various/abc9.ys57
-rw-r--r--tests/various/async.sh8
-rw-r--r--tests/various/blackbox_wb.ys14
-rwxr-xr-xtests/various/logger_fail.sh42
-rw-r--r--tests/various/muxpack.v4
-rw-r--r--tests/various/muxpack.ys4
-rw-r--r--tests/various/param_struct.ys51
-rw-r--r--tests/various/sta.ys81
-rw-r--r--tests/verilog/.gitignore1
-rw-r--r--tests/verilog/absurd_width.ys17
-rw-r--r--tests/verilog/absurd_width_const.ys16
-rw-r--r--tests/verilog/always_comb_latch_1.ys13
-rw-r--r--tests/verilog/always_comb_latch_2.ys15
-rw-r--r--tests/verilog/always_comb_latch_3.ys20
-rw-r--r--tests/verilog/always_comb_latch_4.ys17
-rw-r--r--tests/verilog/always_comb_nolatch_1.ys16
-rw-r--r--tests/verilog/always_comb_nolatch_2.ys17
-rw-r--r--tests/verilog/always_comb_nolatch_3.ys21
-rw-r--r--tests/verilog/always_comb_nolatch_4.ys16
-rw-r--r--tests/verilog/block_end_label_only.ys9
-rw-r--r--tests/verilog/block_end_label_wrong.ys9
-rw-r--r--tests/verilog/doubleslash.ys21
-rw-r--r--tests/verilog/for_decl_no_init.ys9
-rw-r--r--tests/verilog/for_decl_no_sv.ys9
-rw-r--r--tests/verilog/for_decl_shadow.sv32
-rw-r--r--tests/verilog/for_decl_shadow.ys6
-rw-r--r--tests/verilog/func_typename_ret.sv35
-rw-r--r--tests/verilog/func_typename_ret.ys5
-rw-r--r--tests/verilog/gen_block_end_label_only.ys9
-rw-r--r--tests/verilog/gen_block_end_label_wrong.ys9
-rw-r--r--tests/verilog/genfor_decl_no_init.ys7
-rw-r--r--tests/verilog/genfor_decl_no_sv.ys7
-rw-r--r--tests/verilog/genvar_loop_decl_1.sv18
-rw-r--r--tests/verilog/genvar_loop_decl_1.ys14
-rw-r--r--tests/verilog/genvar_loop_decl_2.sv30
-rw-r--r--tests/verilog/genvar_loop_decl_2.ys5
-rw-r--r--tests/verilog/genvar_loop_decl_3.sv28
-rw-r--r--tests/verilog/genvar_loop_decl_3.ys5
-rw-r--r--tests/verilog/global_parameter.ys16
-rw-r--r--tests/verilog/ifdef_nest.ys7
-rw-r--r--tests/verilog/ifdef_unterminated.ys4
-rw-r--r--tests/verilog/localparam_no_default_1.ys17
-rw-r--r--tests/verilog/localparam_no_default_2.ys15
-rw-r--r--tests/verilog/macro_arg_tromp.sv21
-rw-r--r--tests/verilog/macro_arg_tromp.ys2
-rw-r--r--tests/verilog/mem_bounds.sv27
-rw-r--r--tests/verilog/mem_bounds.ys6
-rw-r--r--tests/verilog/module_end_label.ys15
-rw-r--r--tests/verilog/net_types.sv34
-rw-r--r--tests/verilog/net_types.ys5
-rw-r--r--tests/verilog/package_end_label.ys15
-rw-r--r--tests/verilog/package_task_func.sv30
-rw-r--r--tests/verilog/package_task_func.ys4
-rw-r--r--tests/verilog/param_no_default.sv52
-rw-r--r--tests/verilog/param_no_default.ys7
-rw-r--r--tests/verilog/param_no_default_not_svmode.ys26
-rw-r--r--tests/verilog/param_no_default_unbound_1.ys12
-rw-r--r--tests/verilog/param_no_default_unbound_2.ys12
-rw-r--r--tests/verilog/param_no_default_unbound_3.ys12
-rw-r--r--tests/verilog/param_no_default_unbound_4.ys12
-rw-r--r--tests/verilog/param_no_default_unbound_5.ys12
-rw-r--r--tests/verilog/parameters_across_files.ys20
-rw-r--r--tests/verilog/prefix.sv95
-rw-r--r--tests/verilog/prefix.ys5
-rw-r--r--tests/verilog/size_cast.sv140
-rw-r--r--tests/verilog/size_cast.ys5
-rw-r--r--tests/verilog/struct_access.sv88
-rw-r--r--tests/verilog/struct_access.ys4
-rw-r--r--tests/verilog/typedef_across_files.ys23
-rw-r--r--tests/verilog/typedef_legacy_conflict.ys37
-rw-r--r--tests/verilog/unbased_unsized.sv40
-rw-r--r--tests/verilog/unbased_unsized.ys7
-rw-r--r--tests/verilog/unbased_unsized_tern.sv31
-rw-r--r--tests/verilog/unbased_unsized_tern.ys6
-rw-r--r--tests/verilog/unmatched_endif_2.ys7
-rwxr-xr-xtests/vloghtb/run-test.sh2
757 files changed, 49373 insertions, 8621 deletions
diff --git a/.clang-format b/.clang-format
index 28d13da25..c86fa8c1c 100644
--- a/.clang-format
+++ b/.clang-format
@@ -6,7 +6,7 @@ BreakBeforeBraces: Linux
AllowShortIfStatementsOnASingleLine: false
IndentCaseLabels: false
-# From CodingReadme
+# From guidelines/CodingStyle
TabWidth: 8
ContinuationIndentWidth: 2
ColumnLimit: 150
diff --git a/.dockerignore b/.dockerignore
index 9910e9954..9f1da94da 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -6,8 +6,7 @@
Dockerfile
README.md
manual
-CodingReadme
+guidelines
CodeOfConduct
.travis
.travis.yml
-
diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml
new file mode 100644
index 000000000..9aa952e45
--- /dev/null
+++ b/.github/workflows/test-linux.yml
@@ -0,0 +1,125 @@
+name: Build and run tests (Linux)
+
+on: [push, pull_request]
+
+jobs:
+ test-linux:
+ runs-on: ${{ matrix.os.id }}
+ strategy:
+ matrix:
+ os:
+ - { id: ubuntu-20.04, name: focal }
+ compiler:
+ - 'clang-12'
+ - 'clang-11'
+ - 'gcc-11'
+ - 'gcc-10'
+ cpp_std:
+ - 'c++11'
+ - 'c++14'
+ - 'c++17'
+ - 'c++20'
+ include:
+ # Limit the older compilers to C++11 mode
+ - os: { id: ubuntu-18.04, name: bionic }
+ compiler: 'clang-3.9'
+ cpp_std: 'c++11'
+ - os: { id: ubuntu-18.04, name: bionic }
+ compiler: 'gcc-4.8'
+ cpp_std: 'c++11'
+ fail-fast: false
+ steps:
+ - name: Install Dependencies
+ shell: bash
+ run: |
+ sudo apt-get update
+ sudo apt-get install gperf build-essential bison flex libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev
+
+ - name: Setup GCC
+ if: startsWith(matrix.compiler, 'gcc')
+ shell: bash
+ run: |
+ CXX=${CC/#gcc/g++}
+ sudo apt-add-repository ppa:ubuntu-toolchain-r/test
+ sudo apt-get update
+ sudo apt-get install $CC $CXX
+ echo "CC=$CC" >> $GITHUB_ENV
+ echo "CXX=$CXX" >> $GITHUB_ENV
+ env:
+ CC: ${{ matrix.compiler }}
+
+ - name: Setup Clang
+ if: startsWith(matrix.compiler, 'clang')
+ shell: bash
+ run: |
+ wget https://apt.llvm.org/llvm-snapshot.gpg.key
+ sudo apt-key add llvm-snapshot.gpg.key
+ rm llvm-snapshot.gpg.key
+ sudo apt-add-repository "deb https://apt.llvm.org/${{ matrix.os.name }}/ llvm-toolchain-${{ matrix.os.name }} main"
+ sudo apt-get update
+ CXX=${CC/#clang/clang++}
+ sudo apt-get install $CC $CXX
+ echo "CC=$CC" >> $GITHUB_ENV
+ echo "CXX=$CXX" >> $GITHUB_ENV
+ env:
+ CC: ${{ matrix.compiler }}
+
+ - name: Runtime environment
+ shell: bash
+ env:
+ WORKSPACE: ${{ github.workspace }}
+ run: |
+ echo "GITHUB_WORKSPACE=`pwd`" >> $GITHUB_ENV
+ echo "$GITHUB_WORKSPACE/.local/bin" >> $GITHUB_PATH
+ echo "procs=$(nproc)" >> $GITHUB_ENV
+
+ - name: Tool versions
+ shell: bash
+ run: |
+ $CC --version
+ $CXX --version
+
+ - name: Checkout Yosys
+ uses: actions/checkout@v2
+
+ - name: Get iverilog
+ shell: bash
+ run: |
+ git clone https://github.com/steveicarus/iverilog.git
+
+ - name: Cache iverilog
+ id: cache-iverilog
+ uses: actions/cache@v2
+ with:
+ path: .local/
+ key: ${{ matrix.os.id }}-${{ hashFiles('iverilog/.git/refs/heads/master') }}
+
+ - name: Build iverilog
+ if: steps.cache-iverilog.outputs.cache-hit != 'true'
+ shell: bash
+ run: |
+ mkdir -p $GITHUB_WORKSPACE/.local/
+ cd iverilog
+ autoconf
+ CC=gcc CXX=g++ ./configure --prefix=$GITHUB_WORKSPACE/.local
+ make -j${{ env.procs }}
+ make install
+
+ - name: Build yosys (gcc-4.8)
+ if: matrix.compiler == 'gcc-4.8'
+ shell: bash
+ run: |
+ make config-${{ matrix.compiler }}
+ make -j${{ env.procs }} CCXXSTD=${{ matrix.cpp_std }} CC=$CC CXX=$CC LD=$CC
+
+ - name: Build yosys
+ if: matrix.compiler != 'gcc-4.8'
+ shell: bash
+ run: |
+ make config-${CC%%-*}
+ make -j${{ env.procs }} CCXXSTD=${{ matrix.cpp_std }} CC=$CC CXX=$CC LD=$CC
+
+ - name: Run tests
+ shell: bash
+ run: |
+ make -j${{ env.procs }} test CXXSTD=${{ matrix.cpp_std }} CC=$CC CXX=$CC LD=$CC
diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml
new file mode 100644
index 000000000..09ab382bf
--- /dev/null
+++ b/.github/workflows/test-macos.yml
@@ -0,0 +1,154 @@
+name: Build and run tests (macOS)
+
+on: [push, pull_request]
+
+jobs:
+ test-macos:
+ runs-on: ${{ matrix.os.id }}
+ strategy:
+ matrix:
+ os:
+ - { id: macos-11, name: 'Big Sur' }
+ cpp_std:
+ - 'c++11'
+ - 'c++17'
+ fail-fast: false
+ steps:
+ - name: Install Dependencies
+ run: |
+ brew install bison flex gawk libffi pkg-config bash
+
+ - name: Runtime environment
+ shell: bash
+ env:
+ WORKSPACE: ${{ github.workspace }}
+ run: |
+ echo "GITHUB_WORKSPACE=`pwd`" >> $GITHUB_ENV
+ echo "$GITHUB_WORKSPACE/.local/bin" >> $GITHUB_PATH
+ echo "$(brew --prefix bison)/bin" >> $GITHUB_PATH
+ echo "$(brew --prefix flex)/bin" >> $GITHUB_PATH
+ echo "procs=$(sysctl -n hw.ncpu)" >> $GITHUB_ENV
+
+ - name: Tool versions
+ shell: bash
+ run: |
+ cc --version
+
+ - name: Checkout Yosys
+ uses: actions/checkout@v2
+
+ - name: Get iverilog
+ shell: bash
+ run: |
+ git clone https://github.com/steveicarus/iverilog.git
+
+ - name: Cache iverilog
+ id: cache-iverilog
+ uses: actions/cache@v2
+ with:
+ path: .local/
+ key: ${{ matrix.os.id }}-${{ hashFiles('iverilog/.git/refs/heads/master') }}
+
+ - name: Build iverilog
+ if: steps.cache-iverilog.outputs.cache-hit != 'true'
+ shell: bash
+ run: |
+ mkdir -p $GITHUB_WORKSPACE/.local/
+ cd iverilog
+ autoconf
+ CC=gcc CXX=g++ ./configure --prefix=$GITHUB_WORKSPACE/.local/
+ make -j${{ env.procs }}
+ make install
+
+ - name: Build yosys
+ shell: bash
+ run: |
+ make config-clang
+ make -j${{ env.procs }} CXXSTD=${{ matrix.cpp_std }} CC=cc CXX=cc LD=cc
+
+ - name: Run tests
+ shell: bash
+ run: |
+ make -j${{ env.procs }} test CXXSTD=${{ matrix.cpp_std }} CC=cc CXX=cc LD=cc
+
+
+ test-macos-homebrew:
+ runs-on: ${{ matrix.os.id }}
+ strategy:
+ matrix:
+ os:
+ - { id: macos-10.15, name: Catalina }
+ cpp_std:
+ - 'c++17'
+ compiler:
+ - gcc
+ fail-fast: false
+ steps:
+ - name: Install Dependencies
+ run: |
+ brew install bison flex gawk libffi pkg-config bash
+
+ - name: Runtime environment
+ shell: bash
+ env:
+ WORKSPACE: ${{ github.workspace }}
+ run: |
+ echo "GITHUB_WORKSPACE=`pwd`" >> $GITHUB_ENV
+ echo "$GITHUB_WORKSPACE/.local/bin" >> $GITHUB_PATH
+ echo "$(brew --prefix bison)/bin" >> $GITHUB_PATH
+ echo "$(brew --prefix flex)/bin" >> $GITHUB_PATH
+ echo "procs=$(sysctl -n hw.ncpu)" >> $GITHUB_ENV
+
+ - name: Setup compiler
+ shell: bash
+ run: |
+ brew install ${{ matrix.compiler }}
+ CC=${COMPILER/@/-}
+ CXX=${CC/#gcc/g++}
+ echo "CC=$CC" >> $GITHUB_ENV
+ echo "CXX=$CXX" >> $GITHUB_ENV
+ env:
+ COMPILER: ${{ matrix.compiler }}
+
+ - name: Tool versions
+ shell: bash
+ run: |
+ $CC --version
+ $CXX --version
+
+ - name: Checkout Yosys
+ uses: actions/checkout@v2
+
+ - name: Get iverilog
+ shell: bash
+ run: |
+ git clone https://github.com/steveicarus/iverilog.git
+
+ - name: Cache iverilog
+ id: cache-iverilog-homebrew
+ uses: actions/cache@v2
+ with:
+ path: .local/
+ key: ${{ matrix.os.id }}-homebrew-${{ hashFiles('iverilog/.git/refs/heads/master') }}
+
+ - name: Build iverilog
+ if: steps.cache-iverilog.outputs.cache-hit != 'true'
+ shell: bash
+ run: |
+ mkdir -p $GITHUB_WORKSPACE/.local
+ cd iverilog
+ autoconf
+ CC=gcc CXX=g++ ./configure --prefix=$GITHUB_WORKSPACE/.local
+ make -j${{ env.procs }}
+ make install
+
+ - name: Build yosys
+ shell: bash
+ run: |
+ make config-gcc
+ make -j${{ env.procs }} CXXSTD=${{ matrix.cpp_std }} CC=$CC CXX=$CC LD=$CC
+
+ - name: Run tests
+ shell: bash
+ run: |
+ make -j${{ env.procs }} test CXXSTD=${{ matrix.cpp_std }} CC=$CC CXX=$CC LD=$CC
diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml
new file mode 100644
index 000000000..c6f4da30d
--- /dev/null
+++ b/.github/workflows/version.yml
@@ -0,0 +1,34 @@
+name: Bump version
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: '0 0 * * *'
+
+jobs:
+ bump-version:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+ - name: Take last commit
+ id: log
+ run: echo "::set-output name=message::$(git log --no-merges -1 --oneline)"
+ - name: Take repository
+ id: repo
+ run: echo "::set-output name=message::$GITHUB_REPOSITORY"
+ - name: Bump version
+ if: "!contains(steps.log.outputs.message, 'Bump version') && contains(steps.repo.outputs.message, 'YosysHQ/yosys')"
+ run: |
+ make bumpversion
+ git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
+ git config --local user.name "github-actions[bot]"
+ git add Makefile
+ git commit -m "Bump version"
+ - name: Push changes # push the output folder to your repo
+ if: "!contains(steps.log.outputs.message, 'Bump version') && contains(steps.repo.outputs.message, 'YosysHQ/yosys')"
+ uses: ad-m/github-push-action@master
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/vs.yml b/.github/workflows/vs.yml
new file mode 100644
index 000000000..79a8401d6
--- /dev/null
+++ b/.github/workflows/vs.yml
@@ -0,0 +1,37 @@
+name: Visual Studio Build
+
+on: [push, pull_request]
+
+jobs:
+ yosys-vcxsrc:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Cache sources
+ id: cache-sources
+ uses: actions/cache@v2
+ with:
+ path: .
+ key: cache-yosys
+ - name: Build
+ run: make vcxsrc YOSYS_VER=latest
+ - uses: actions/upload-artifact@v2
+ with:
+ name: vcxsrc
+ path: yosys-win32-vcxsrc-latest.zip
+
+ build:
+ runs-on: windows-2019
+ needs: yosys-vcxsrc
+ steps:
+ - uses: actions/download-artifact@v2
+ with:
+ name: vcxsrc
+ path: .
+ - name: unzip
+ run: unzip yosys-win32-vcxsrc-latest.zip
+ - name: setup-msbuild
+ uses: microsoft/setup-msbuild@v1
+ - name: MSBuild
+ working-directory: yosys-win32-vcxsrc-latest
+ run: msbuild YosysVS.sln /p:PlatformToolset=v142 /p:Configuration=Release /p:WindowsTargetPlatformVersion=10.0.17763.0
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 000000000..78afe1b6c
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,7 @@
+Marcelina Kościelnicka <mwk@0x04.net>
+Marcelina Kościelnicka <mwk@0x04.net> <koriakin@0x04.net>
+Marcelina Kościelnicka <mwk@0x04.net> <marcin@symbioticeda.com>
+Claire Xenia Wolf <claire@yosyshq.com> <claire@clairexen.net>
+Claire Xenia Wolf <claire@yosyshq.com> <claire@symbioticeda.com>
+Claire Xenia Wolf <claire@yosyshq.com> <clifford@symbioticeda.com>
+Claire Xenia Wolf <claire@yosyshq.com> <clifford@clifford.at>
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 09f380831..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,144 +0,0 @@
-sudo: false
-language: cpp
-
-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
- - python3
- - libboost-system-dev
- - libboost-python-dev
- - libboost-filesystem-dev
- - zlib1g-dev
- env:
- - MATRIX_EVAL="CONFIG=gcc && CC=gcc-4.8 && CXX=g++-4.8"
-
- # Latest gcc supported on Travis Linux
- - os: linux
- addons:
- apt:
- sources:
- - ubuntu-toolchain-r-test
- packages:
- - g++-9
- - gperf
- - build-essential
- - bison
- - flex
- - libreadline-dev
- - gawk
- - tcl-dev
- - libffi-dev
- - git
- - graphviz
- - xdot
- - pkg-config
- - python
- - python3
- - libboost-system-dev
- - libboost-python-dev
- - libboost-filesystem-dev
- - zlib1g-dev
- env:
- - MATRIX_EVAL="CONFIG=gcc && CC=gcc-9 && CXX=g++-9"
-
- # 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
- - python3
- - libboost-system-dev
- - libboost-python-dev
- - libboost-filesystem-dev
- - zlib1g-dev
- 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-xenial-8
- packages:
- - clang-8
- - gperf
- - build-essential
- - bison
- - flex
- - libreadline-dev
- - gawk
- - tcl-dev
- - libffi-dev
- - git
- - graphviz
- - xdot
- - pkg-config
- - python
- - python3
- - libboost-system-dev
- - libboost-python-dev
- - libboost-filesystem-dev
- - zlib1g-dev
- env:
- - MATRIX_EVAL="CONFIG=clang && CC=clang-8 && CXX=clang++-8"
-
-# # Latest clang on Mac OS X
-# - os: osx
-# osx_image: xcode9.4
-# env:
-# - MATRIX_EVAL="CONFIG=clang && CC=clang && CXX=clang++"
-
-before_install:
- - ./.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
deleted file mode 100755
index 801407d1e..000000000
--- a/.travis/build-and-test.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#! /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 CC=$CC CXX=$CC LD=$CC
-
-echo
-echo -en 'travis_fold:end:script.build\\r'
-echo
-
-##########################################################################
-
-./yosys tests/simple/fiedler-cooley.v
-
-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
deleted file mode 100644
index 8eecc4c09..000000000
--- a/.travis/common.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#! /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
deleted file mode 100755
index d64e95244..000000000
--- a/.travis/deploy-after-success.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#! /bin/bash
-
-set -x
-set -e
-
-# FIXME: Upload the build results somewhere...
diff --git a/.travis/setup.sh b/.travis/setup.sh
deleted file mode 100755
index 02879b974..000000000
--- a/.travis/setup.sh
+++ /dev/null
@@ -1,63 +0,0 @@
-#! /bin/bash
-
-set -e
-
-source .travis/common.sh
-
-##########################################################################
-
-# Output status information.
-(
- set +e
- set -x
- git status
- git branch -v
- git log -n 5 --graph
- git log --format=oneline -n 20 --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
- 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
- CC=gcc CXX=g++ ./configure --prefix=$HOME/.local-bin
- make
- make install
- echo
- echo -en 'travis_fold:end:before_install.iverilog\\r'
- echo
- fi
-)
-
-##########################################################################
diff --git a/CHANGELOG b/CHANGELOG
index 6dcd05de6..1451ea07c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,74 +2,246 @@
List of major changes and improvements between releases
=======================================================
+Yosys 0.14 .. Yosys 0.14-dev
+--------------------------
-Yosys 0.9 .. Yosys 0.9-dev
+Yosys 0.13 .. Yosys 0.14
--------------------------
* Various
+ - Added $bmux and $demux cells and related optimization patterns.
+
+ * New commands and options
+ - Added "bmuxmap" and "dmuxmap" passes
+ - Added "-fst" option to "sim" pass for writing FST files
+ - Added "-r", "-scope", "-start", "-stop", "-at", "-sim", "-sim-gate",
+ "-sim-gold" options to "sim" pass for co-simulation
+
+ * Anlogic support
+ - Added support for BRAMs
+
+Yosys 0.12 .. Yosys 0.13
+--------------------------
+
+ * Various
+ - Use "read" command to parse HDL files from Yosys command-line
+ - Added "yosys -r <topmodule>" command line option
+ - write_verilog: dump zero width sigspecs correctly
+
+ * SystemVerilog
+ - Fixed regression preventing the use array querying functions in case
+ expressions and case item expressions
+ - Fixed static size casts inadvertently limiting the result width of binary
+ operations
+ - Fixed static size casts ignoring expression signedness
+ - Fixed static size casts not extending unbased unsized literals
+ - Added automatic `nosync` inference for local variables in `always_comb`
+ procedures which are always assigned before they are used to avoid errant
+ latch inference
+
+ * New commands and options
+ - Added "clean_zerowidth" pass
+
+ * Verific support
+ - Add YOSYS to the implicitly defined verilog macros in verific
+
+Yosys 0.11 .. Yosys 0.12
+--------------------------
+
+ * Various
+ - Added iopadmap native support for negative-polarity output enable
+ - ABC update
+
+ * SystemVerilog
+ - Support parameters using struct as a wiretype
+
+ * New commands and options
+ - Added "-genlib" option to "abc" pass
+ - Added "sta" very crude static timing analysis pass
+
+ * Verific support
+ - Fixed memory block size in import
+
+ * New back-ends
+ - Added support for GateMate FPGA from Cologne Chip AG
+
+ * Intel ALM support
+ - Added preliminary Arria V support
+
+
+Yosys 0.10 .. Yosys 0.11
+--------------------------
+
+ * Various
+ - Added $aldff and $aldffe (flip-flops with async load) cells
+
+ * SystemVerilog
+ - Fixed an issue which prevented writing directly to a memory word via a
+ connection to an output port
+ - Fixed an issue which prevented unbased unsized literals (e.g., `'1`) from
+ filling the width of a cell input
+ - Fixed an issue where connecting a slice covering the entirety of a signed
+ signal to a cell input would cause a failed assertion
+
+ * Verific support
+ - Importer support for {PRIM,WIDE_OPER}_DFF
+ - Importer support for PRIM_BUFIF1
+ - Option to use Verific without VHDL support
+ - Importer support for {PRIM,WIDE_OPER}_DLATCH{,RS}
+ - Added -cfg option for getting/setting Verific runtime flags
+
+Yosys 0.9 .. Yosys 0.10
+--------------------------
+
+ * Various
+ - Added automatic gzip decompression for frontends
+ - Added $_NMUX_ cell type
+ - Added automatic gzip compression (based on filename extension) for backends
+ - Improve attribute and parameter encoding in JSON to avoid ambiguities between
+ bit vectors and strings containing [01xz]*
+ - Improvements in pmgen: subpattern and recursive matches
+ - Support explicit FIRRTL properties
+ - Improvements in pmgen: slices, choices, define, generate
+ - Added "_TECHMAP_WIREINIT_*_" parameter and "_TECHMAP_REMOVEINIT_*_" wire for "techmap" pass
+ - Added +/mul2dsp.v for decomposing wide multipliers to custom-sized ones
+ - Added new frontend: rpc
+ - Added --version and -version as aliases for -V
+ - Improve yosys-smtbmc "solver not found" handling
+ - Improved support of $readmem[hb] Memory Content File inclusion
+ - Added CXXRTL backend
+ - Use YosysHQ/abc instead of upstream berkeley-abc/abc
+ - Added WASI platform support.
+ - Added extmodule support to firrtl backend
+ - Added $divfloor and $modfloor cells
+ - Added $adffe, $dffsre, $sdff, $sdffe, $sdffce, $adlatch cells
+ - Added "_TECHMAP_CELLNAME_" parameter for "techmap" pass
+ - Added firrtl backend support for generic parameters in blackbox components
+ - Added $meminit_v2 cells (with support for write mask)
+ - Added $mem_v2, $memrd_v2, $memwr_v2, with the following features:
+ - write priority masks, per write/write port pair
+ - transparency and undefined collision behavior masks, per read/write port pair
+ - read port reset and initialization
+ - wide ports (accessing a naturally aligned power-of-two number of memory cells)
+
+ * New commands and options
- Added "write_xaiger" backend
+ - Added "read_xaiger"
- Added "abc9" pass for timing-aware techmapping (experimental, FPGA only)
- - Added "synth_xilinx -abc9" (experimental)
- - Added "synth_ice40 -abc9" (experimental)
- Added "synth -abc9" (experimental)
- Added "script -scriptwire"
+ - Added "clkbufmap" pass
+ - Added "extractinv" pass and "invertible_pin" attribute
+ - Added "proc_clean -quiet"
+ - Added "proc_prune" pass
+ - Added "stat -tech cmos"
+ - Added "opt_share" pass, run as part of "opt -full"
+ - Added "-match-init" option to "dff2dffs" pass
+ - Added "equiv_opt -multiclock"
+ - Added "techmap_autopurge" support to techmap
+ - Added "add -mod <modname[s]>"
+ - Added "paramap" pass
+ - Added "portlist" command
+ - Added "check -mapped"
+ - Added "check -allow-tbuf"
+ - Added "autoname" pass
+ - Added "write_verilog -extmem"
+ - Added "opt_mem" pass
+ - Added "scratchpad" pass
+ - Added "fminit" pass
+ - Added "opt_lut_ins" pass
+ - Added "logger" pass
+ - Added "show -nobg"
+ - Added "exec" command
+ - Added "design -delete"
+ - Added "design -push-copy"
+ - Added "qbfsat" command
+ - Added "select -unset"
+ - Added "dfflegalize" pass
+ - Removed "opt_expr -clkinv" option, made it the default
+ - Added "proc -nomux
+ - Merged "dffsr2dff", "opt_rmdff", "dff2dffe", "dff2dffs", "peepopt.dffmux" passes into a new "opt_dff" pass
+
+ * SystemVerilog
+ - Added checking of always block types (always_comb, always_latch and always_ff)
+ - Added support for wildcard port connections (.*)
+ - Added support for enum typedefs
+ - Added support for structs and packed unions.
+ - Allow constant function calls in for loops and generate if and case
+ - Added support for static cast
+ - Added support for logic typed parameters
+ - Fixed generate scoping issues
+ - Added support for real-valued parameters
+ - Allow localparams in constant functions
+ - Module name scope support
+ - Support recursive functions using ternary expressions
+ - Extended support for integer types
+ - Support for parameters without default values
+ - Allow globals in one file to depend on globals in another
+ - Added support for: *=, /=, %=, <<=, >>=, <<<=, >>>=
+ - Added support for parsing the 'bind' construct
+ - support declaration in procedural for initialization
+ - support declaration in generate for initialization
+ - Support wand and wor of data types
+
+ * Verific support
+ - Added "verific -L"
+ - Add Verific SVA support for "always" properties
+ - Add Verific support for SVA nexttime properties
+ - Improve handling of verific primitives in "verific -import -V" mode
+ - Import attributes for wires
+ - Support VHDL enums
+ - Added support for command files
+
+ * New back-ends
+ - Added initial EFINIX support
+ - Added Intel ALM: alternative synthesis for Intel FPGAs
+ - Added initial Nexus support
+ - Added initial MachXO2 support
+ - Added initial QuickLogic PolarPro 3 support
+
+ * ECP5 support
+ - Renamed labels/options in synth_ecp5 (e.g. dram -> map_lutram; -nodram -> -nolutram)
+ - Added "synth_ecp5 -abc9" (experimental)
+ - Added "synth_ecp5 -nowidelut"
+ - "synth_ecp5" to now infer DSP blocks (-nodsp to disable, experimental)
+
+ * iCE40 support
+ - Added "synth_ice40 -abc9" (experimental)
+ - Added "synth_ice40 -device"
+ - Renamed labels/options in synth_ice40 (e.g. dram -> map_lutram; -nodram -> -nolutram)
+ - Added "ice40_wrapcarry" to encapsulate SB_LUT+SB_CARRY pairs for techmapping
+ - Removed "ice40_unlut"
+ - Added "ice40_dsp" for Lattice iCE40 DSP packing
+ - "synth_ice40 -dsp" to infer DSP blocks
+
+ * Xilinx support
+ - Added "synth_xilinx -abc9" (experimental)
- Added "synth_xilinx -nocarry"
- Added "synth_xilinx -nowidelut"
- - Added "synth_ecp5 -nowidelut"
- "synth_xilinx" to now infer wide multiplexers (-widemux <min> to enable)
- - Renamed labels/options in synth_ice40 (e.g. dram -> map_lutram; -nodram -> -nolutram)
- - Renamed labels/options in synth_ecp5 (e.g. dram -> map_lutram; -nodram -> -nolutram)
- - Renamed labels in synth_intel (e.g. bram -> map_bram)
- Renamed labels/options in synth_xilinx (e.g. dram -> map_lutram; -nodram -> -nolutram)
- - Added automatic gzip decompression for frontends
- - Added $_NMUX_ cell type
- - Added automatic gzip compression (based on filename extension) for backends
- - Improve attribute and parameter encoding in JSON to avoid ambiguities between
- bit vectors and strings containing [01xz]*
- - Added "clkbufmap" pass
- - Added "extractinv" pass and "invertible_pin" attribute
- Added "synth_xilinx -family xc6s" for Spartan 6 support (experimental)
- Added "synth_xilinx -ise" (experimental)
- Added "synth_xilinx -iopad"
- "synth_xilinx" now automatically inserts clock buffers (add -noclkbuf to disable)
- - Improvements in pmgen: subpattern and recursive matches
- - Added "opt_share" pass, run as part of "opt -full"
- - Added "ice40_wrapcarry" to encapsulate SB_LUT+SB_CARRY pairs for techmapping
- - Removed "ice40_unlut"
- - Improvements in pmgen: slices, choices, define, generate
- Added "xilinx_srl" for Xilinx shift register extraction
- Removed "shregmap -tech xilinx" (superseded by "xilinx_srl")
- - Added "_TECHMAP_WIREINIT_*_" parameter and "_TECHMAP_REMOVEINIT_*_" wire for "techmap" pass
- - Added "-match-init" option to "dff2dffs" pass
- - Added "techmap_autopurge" support to techmap
- - Added "add -mod <modname[s]>"
- - Added +/mul2dsp.v for decomposing wide multipliers to custom-sized ones
- - Added "ice40_dsp" for Lattice iCE40 DSP packing
- Added "xilinx_dsp" for Xilinx DSP packing
- "synth_xilinx" to now infer DSP blocks (-nodsp to disable)
- - "synth_ecp5" to now infer DSP blocks (-nodsp to disable, experimental)
- - "synth_ice40 -dsp" to infer DSP blocks
- Added latch support to synth_xilinx
- Added support for flip-flops with synchronous reset to synth_xilinx
- Added support for flip-flops with reset and enable to synth_xilinx
- - Added "check -mapped"
- - Added checking of SystemVerilog always block types (always_comb,
- always_latch and always_ff)
- - Added support for SystemVerilog wildcard port connections (.*)
- Added "xilinx_dffopt" pass
- - Added "scratchpad" pass
- Added "synth_xilinx -dff"
- - Improved support of $readmem[hb] Memory Content File inclusion
- - Added "opt_lut_ins" pass
- - Added "logger" pass
- - Added "design -delete"
- - Added "select -unset"
- - Use YosysHQ/abc instead of upstream berkeley-abc/abc
- - Added $divfloor and $modfloor cells
- - Added $adffe, $dffsre, $sdff, $sdffe, $sdffce, $adlatch cells
- - Added "dfflegalize" pass
- - Added "_TECHMAP_CELLNAME_" parameter for "techmap" pass
- - Merged "dffsr2dff", "opt_rmdff", "dff2dffe", "dff2dffs", "peepopt.dffmux" passes into a new "opt_dff" pass
+
+ * Intel support
+ - Renamed labels in synth_intel (e.g. bram -> map_bram)
+ - synth_intel: cyclone10 -> cyclone10lp, a10gx -> arria10gx
+ - Added "intel_alm -abc9" (experimental)
+
+ * CoolRunner2 support
+ - Separate and improve buffer cell insertion pass
+ - Use extract_counter to optimize counters
Yosys 0.8 .. Yosys 0.9
----------------------
diff --git a/CODEOWNERS b/CODEOWNERS
index 0419e6e44..11a8cc026 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -16,6 +16,8 @@ backends/cxxrtl/ @whitequark
passes/cmds/bugpoint.cc @whitequark
passes/techmap/flowmap.cc @whitequark
passes/opt/opt_lut.cc @whitequark
+passes/techmap/abc9*.cc @eddiehung
+backends/aiger/xaiger.cc @eddiehung
## External Contributors
@@ -29,6 +31,8 @@ frontends/verilog/ @zachjs
frontends/ast/ @zachjs
techlibs/intel_alm/ @ZirconiumX
+techlibs/gowin/ @pepijndevos
+techlibs/gatemate/ @pu-cc
# pyosys
misc/*.py @btut
@@ -38,4 +42,5 @@ backends/firrtl @ucbjrl @azidar
passes/sat/qbfsat.cc @boqwxp
passes/sat/qbfsat.h @boqwxp
passes/cmds/exec.cc @boqwxp
+passes/cmds/glift.cc @boqwxp
passes/cmds/printattrs.cc @boqwxp
diff --git a/COPYING b/COPYING
index 7cd2464cd..e8b123be2 100644
--- a/COPYING
+++ b/COPYING
@@ -1,6 +1,6 @@
ISC License
-Copyright (C) 2012 - 2020 Claire Wolf <claire@symbioticeda.com>
+Copyright (C) 2012 - 2020 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/Makefile b/Makefile
index 1fed7ae0e..6e7e9f59f 100644
--- a/Makefile
+++ b/Makefile
@@ -18,6 +18,8 @@ ENABLE_READLINE := 1
ENABLE_EDITLINE := 0
ENABLE_GHDL := 0
ENABLE_VERIFIC := 0
+DISABLE_VERIFIC_EXTENSIONS := 0
+DISABLE_VERIFIC_VHDL := 0
ENABLE_COVER := 1
ENABLE_LIBYOSYS := 0
ENABLE_PROTOBUF := 0
@@ -85,6 +87,7 @@ all: top-all
YOSYS_SRC := $(dir $(firstword $(MAKEFILE_LIST)))
VPATH := $(YOSYS_SRC)
+CXXSTD ?= c++11
CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -ggdb -I. -I"$(YOSYS_SRC)" -MD -MP -D_YOSYS_ -fPIC -I$(PREFIX)/include
LDLIBS := $(LDLIBS) -lstdc++ -lm
PLUGIN_LDFLAGS :=
@@ -126,12 +129,12 @@ LDFLAGS += -rdynamic
LDLIBS += -lrt
endif
-YOSYS_VER := 0.9+3981
-GIT_REV := $(shell cd $(YOSYS_SRC) && git rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
+YOSYS_VER := 0.14+6
+GIT_REV := $(shell git -C $(YOSYS_SRC) rev-parse --short HEAD 2> /dev/null || echo UNKNOWN)
OBJS = kernel/version_$(GIT_REV).o
bumpversion:
- sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 8a4c6e6.. | wc -l`/;" Makefile
+ sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline a4522d6.. | wc -l`/;" Makefile
# set 'ABCREV = default' to use abc/ as it is
#
@@ -139,10 +142,10 @@ bumpversion:
# 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 = 4f5f73d
+ABCREV = f6fa2dd
ABCPULL = 1
ABCURL ?= https://github.com/YosysHQ/abc
-ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1
+ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 VERBOSE=$(Q)
# 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.
@@ -186,21 +189,21 @@ endif
ifeq ($(CONFIG),clang)
CXX = clang
LD = clang++
-CXXFLAGS += -std=c++11 -Os
+CXXFLAGS += -std=$(CXXSTD) -Os
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
ifneq ($(SANITIZER),)
$(info [Clang Sanitizer] $(SANITIZER))
CXXFLAGS += -g -O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=$(SANITIZER)
LDFLAGS += -g -fsanitize=$(SANITIZER)
-ifeq ($(SANITIZER),address)
+ifneq ($(findstring address,$(SANITIZER)),)
ENABLE_COVER := 0
endif
-ifeq ($(SANITIZER),memory)
+ifneq ($(findstring memory,$(SANITIZER)),)
CXXFLAGS += -fPIE -fsanitize-memory-track-origins
LDFLAGS += -fPIE -fsanitize-memory-track-origins
endif
-ifeq ($(SANITIZER),cfi)
+ifneq ($(findstring cfi,$(SANITIZER)),)
CXXFLAGS += -flto
LDFLAGS += -flto
endif
@@ -209,7 +212,7 @@ endif
else ifeq ($(CONFIG),gcc)
CXX = gcc
LD = gcc
-CXXFLAGS += -std=c++11 -Os
+CXXFLAGS += -std=$(CXXSTD) -Os
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
else ifeq ($(CONFIG),gcc-static)
@@ -217,7 +220,7 @@ LD = $(CXX)
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -static
LDLIBS := $(filter-out -lrt,$(LDLIBS))
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
-CXXFLAGS += -std=c++11 -Os
+CXXFLAGS += -std=$(CXXSTD) -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)
@@ -227,13 +230,13 @@ endif
else ifeq ($(CONFIG),gcc-4.8)
CXX = gcc-4.8
LD = gcc-4.8
-CXXFLAGS += -std=c++11 -Os
+CXXFLAGS += -std=$(CXXSTD) -Os
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
else ifeq ($(CONFIG),afl-gcc)
CXX = AFL_QUIET=1 AFL_HARDEN=1 afl-gcc
LD = AFL_QUIET=1 AFL_HARDEN=1 afl-gcc
-CXXFLAGS += -std=c++11 -Os
+CXXFLAGS += -std=$(CXXSTD) -Os
ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
else ifeq ($(CONFIG),cygwin)
@@ -245,7 +248,7 @@ ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H"
else ifeq ($(CONFIG),emcc)
CXX = emcc
LD = emcc
-CXXFLAGS := -std=c++11 $(filter-out -fPIC -ggdb,$(CXXFLAGS))
+CXXFLAGS := -std=$(CXXSTD) $(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
@@ -295,7 +298,7 @@ AR = $(WASI_SDK)/bin/ar
RANLIB = $(WASI_SDK)/bin/ranlib
WASIFLAGS := --sysroot $(WASI_SDK)/share/wasi-sysroot $(WASIFLAGS)
endif
-CXXFLAGS := $(WASIFLAGS) -std=c++11 -Os $(filter-out -fPIC,$(CXXFLAGS))
+CXXFLAGS := $(WASIFLAGS) -std=$(CXXSTD) -Os $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(WASIFLAGS) -Wl,-z,stack-size=1048576 $(filter-out -rdynamic,$(LDFLAGS))
LDLIBS := $(filter-out -lrt,$(LDLIBS))
ABCMKARGS += AR="$(AR)" RANLIB="$(RANLIB)"
@@ -314,7 +317,7 @@ else ifeq ($(CONFIG),mxe)
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 += -std=$(CXXSTD) -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))
@@ -326,7 +329,7 @@ EXE = .exe
else ifeq ($(CONFIG),msys2-32)
CXX = i686-w64-mingw32-g++
LD = i686-w64-mingw32-g++
-CXXFLAGS += -std=c++11 -Os -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR
+CXXFLAGS += -std=$(CXXSTD) -Os -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
LDLIBS := $(filter-out -lrt,$(LDLIBS))
@@ -337,7 +340,7 @@ 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 += -std=$(CXXSTD) -Os -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR
CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS))
LDFLAGS := $(filter-out -rdynamic,$(LDFLAGS)) -s
LDLIBS := $(filter-out -lrt,$(LDLIBS))
@@ -354,53 +357,29 @@ TARGETS += libyosys.so
endif
ifeq ($(ENABLE_PYOSYS),1)
-
-#Detect name of boost_python library. Some distros usbe boost_python-py<version>, other boost_python<version>, some only use the major version number, some a concatenation of major and minor version numbers
-ifeq ($(OS), Darwin)
-BOOST_PYTHON_LIB ?= $(shell \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
- echo ""; fi; fi; fi; fi;)
-else
+# Detect name of boost_python library. Some distros use boost_python-py<version>, other boost_python<version>, some only use the major version number, some a concatenation of major and minor version numbers
+CHECK_BOOST_PYTHON = (echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -l$(1) - > /dev/null 2>&1 && echo "-l$(1)")
BOOST_PYTHON_LIB ?= $(shell \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python-py$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_VERSION))"; else \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python-py$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python$(subst .,,$(PYTHON_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_VERSION))"; else \
- if echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null `$(PYTHON_CONFIG) --libs` -lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION)) - > /dev/null 2>&1; then echo "-lboost_python$(subst .,,$(PYTHON_MAJOR_VERSION))"; else \
- echo ""; fi; fi; fi; fi;)
-endif
+ $(call CHECK_BOOST_PYTHON,boost_python-py$(subst .,,$(PYTHON_VERSION))) || \
+ $(call CHECK_BOOST_PYTHON,boost_python-py$(PYTHON_MAJOR_VERSION)) || \
+ $(call CHECK_BOOST_PYTHON,boost_python$(subst .,,$(PYTHON_VERSION))) || \
+ $(call CHECK_BOOST_PYTHON,boost_python$(PYTHON_MAJOR_VERSION)) \
+)
ifeq ($(BOOST_PYTHON_LIB),)
$(error BOOST_PYTHON_LIB could not be detected. Please define manually)
endif
-ifeq ($(OS), Darwin)
-ifeq ($(PYTHON_MAJOR_VERSION),3)
-LDLIBS += $(shell $(PYTHON_CONFIG) --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
-CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON
-else
-LDLIBS += $(shell $(PYTHON_CONFIG) --ldflags) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
-CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON
-endif
-else
-ifeq ($(PYTHON_MAJOR_VERSION),3)
-LDLIBS += $(shell $(PYTHON_CONFIG) --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
-CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON
-else
LDLIBS += $(shell $(PYTHON_CONFIG) --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem
+# python-config --ldflags includes LDLIBS for some reason
+LDFLAGS += $(filter-out -l%,$(shell $(PYTHON_CONFIG) --ldflags))
CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON
-endif
-endif
-ifeq ($(ENABLE_PYOSYS),1)
PY_WRAPPER_FILE = kernel/python_wrappers
OBJS += $(PY_WRAPPER_FILE).o
PY_GEN_SCRIPT= py_wrap_generator
PY_WRAP_INCLUDES := $(shell python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).print_includes()")
-endif
-endif
+endif # ENABLE_PYOSYS
ifeq ($(ENABLE_READLINE),1)
CXXFLAGS += -DYOSYS_ENABLE_READLINE
@@ -522,7 +501,19 @@ endif
ifeq ($(ENABLE_VERIFIC),1)
VERIFIC_DIR ?= /usr/local/src/verific_lib
-VERIFIC_COMPONENTS ?= verilog vhdl database util containers hier_tree
+VERIFIC_COMPONENTS ?= verilog database util containers hier_tree
+ifneq ($(DISABLE_VERIFIC_VHDL),1)
+VERIFIC_COMPONENTS += vhdl
+CXXFLAGS += -DVERIFIC_VHDL_SUPPORT
+else
+ifneq ($(wildcard $(VERIFIC_DIR)/vhdl),)
+VERIFIC_COMPONENTS += vhdl
+endif
+endif
+ifneq ($(DISABLE_VERIFIC_EXTENSIONS),1)
+VERIFIC_COMPONENTS += extensions
+CXXFLAGS += -DYOSYSHQ_VERIFIC_EXTENSIONS
+endif
CXXFLAGS += $(patsubst %,-I$(VERIFIC_DIR)/%,$(VERIFIC_COMPONENTS)) -DYOSYS_ENABLE_VERIFIC
ifeq ($(OS), Darwin)
LDLIBS += $(patsubst %,$(VERIFIC_DIR)/%/*-mac.a,$(VERIFIC_COMPONENTS)) -lz
@@ -589,6 +580,7 @@ $(eval $(call add_include_file,kernel/yosys.h))
$(eval $(call add_include_file,kernel/hashlib.h))
$(eval $(call add_include_file,kernel/log.h))
$(eval $(call add_include_file,kernel/rtlil.h))
+$(eval $(call add_include_file,kernel/binding.h))
$(eval $(call add_include_file,kernel/register.h))
$(eval $(call add_include_file,kernel/celltypes.h))
$(eval $(call add_include_file,kernel/celledges.h))
@@ -599,15 +591,20 @@ $(eval $(call add_include_file,kernel/modtools.h))
$(eval $(call add_include_file,kernel/macc.h))
$(eval $(call add_include_file,kernel/utils.h))
$(eval $(call add_include_file,kernel/satgen.h))
+$(eval $(call add_include_file,kernel/qcsat.h))
$(eval $(call add_include_file,kernel/ff.h))
$(eval $(call add_include_file,kernel/ffinit.h))
+$(eval $(call add_include_file,kernel/fstdata.h))
$(eval $(call add_include_file,kernel/mem.h))
$(eval $(call add_include_file,libs/ezsat/ezsat.h))
$(eval $(call add_include_file,libs/ezsat/ezminisat.h))
+$(eval $(call add_include_file,libs/fst/fstapi.h))
$(eval $(call add_include_file,libs/sha1/sha1.h))
$(eval $(call add_include_file,libs/json11/json11.hpp))
$(eval $(call add_include_file,passes/fsm/fsmdata.h))
$(eval $(call add_include_file,frontends/ast/ast.h))
+$(eval $(call add_include_file,frontends/ast/ast_binding.h))
+$(eval $(call add_include_file,frontends/blif/blifparse.h))
$(eval $(call add_include_file,backends/rtlil/rtlil_backend.h))
$(eval $(call add_include_file,backends/cxxrtl/cxxrtl.h))
$(eval $(call add_include_file,backends/cxxrtl/cxxrtl_vcd.h))
@@ -617,12 +614,13 @@ $(eval $(call add_include_file,backends/cxxrtl/cxxrtl_vcd_capi.cc))
$(eval $(call add_include_file,backends/cxxrtl/cxxrtl_vcd_capi.h))
OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o
+OBJS += kernel/binding.o
ifeq ($(ENABLE_ABC),1)
ifneq ($(ABCEXTERNAL),)
kernel/yosys.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
endif
endif
-OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/mem.o
+OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/fstdata.o
kernel/log.o: CXXFLAGS += -DYOSYS_SRC='"$(YOSYS_SRC)"'
kernel/yosys.o: CXXFLAGS += -DYOSYS_DATDIR='"$(DATDIR)"' -DYOSYS_PROGRAM_PREFIX='"$(PROGRAM_PREFIX)"'
@@ -646,6 +644,10 @@ OBJS += libs/minisat/SimpSolver.o
OBJS += libs/minisat/Solver.o
OBJS += libs/minisat/System.o
+OBJS += libs/fst/fstapi.o
+OBJS += libs/fst/fastlz.o
+OBJS += libs/fst/lz4.o
+
include $(YOSYS_SRC)/frontends/*/Makefile.inc
include $(YOSYS_SRC)/passes/*/Makefile.inc
include $(YOSYS_SRC)/backends/*/Makefile.inc
@@ -699,9 +701,9 @@ $(PROGRAM_PREFIX)yosys$(EXE): $(OBJS)
libyosys.so: $(filter-out kernel/driver.o,$(OBJS))
ifeq ($(OS), Darwin)
- $(P) $(LD) -o libyosys.so -shared -Wl,-install_name,$(DESTDIR)$(LIBDIR)/libyosys.so $(LDFLAGS) $^ $(LDLIBS)
+ $(P) $(LD) -o libyosys.so -shared -Wl,-install_name,$(LIBDIR)/libyosys.so $(LDFLAGS) $^ $(LDLIBS)
else
- $(P) $(LD) -o libyosys.so -shared -Wl,-soname,$(DESTDIR)$(LIBDIR)/libyosys.so $(LDFLAGS) $^ $(LDLIBS)
+ $(P) $(LD) -o libyosys.so -shared -Wl,-soname,$(LIBDIR)/libyosys.so $(LDFLAGS) $^ $(LDLIBS)
endif
%.o: %.cc
@@ -749,7 +751,7 @@ ifneq ($(ABCREV),default)
$(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 \
+ $(Q) if test -d abc && ! git -C abc 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
# set a variable so the test fails if git fails to run - when comparing outputs directly, empty string would match empty string
@@ -761,7 +763,7 @@ ifneq ($(ABCREV),default)
fi
endif
$(Q) rm -f abc/abc-[0-9a-f]*
- $(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)
+ $(Q) $(MAKE) -C abc $(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)
@@ -804,6 +806,7 @@ test: $(TARGETS) $(EXTRA_TARGETS)
+cd tests/svinterfaces && bash run-test.sh $(SEEDOPT)
+cd tests/svtypes && bash run-test.sh $(SEEDOPT)
+cd tests/proc && bash run-test.sh
+ +cd tests/blif && bash run-test.sh
+cd tests/opt && bash run-test.sh
+cd tests/aiger && bash run-test.sh $(ABCOPT)
+cd tests/arch && bash run-test.sh
@@ -816,6 +819,8 @@ test: $(TARGETS) $(EXTRA_TARGETS)
+cd tests/arch/gowin && bash run-test.sh $(SEEDOPT)
+cd tests/arch/intel_alm && bash run-test.sh $(SEEDOPT)
+cd tests/arch/nexus && bash run-test.sh $(SEEDOPT)
+ +cd tests/arch/quicklogic && bash run-test.sh $(SEEDOPT)
+ +cd tests/arch/gatemate && bash run-test.sh $(SEEDOPT)
+cd tests/rpc && bash run-test.sh
+cd tests/memfile && bash run-test.sh
+cd tests/verilog && bash run-test.sh
@@ -954,7 +959,7 @@ ifeq ($(ENABLE_ABC),1)
cp -r $(PROGRAM_PREFIX)yosys-abc.exe abc/lib/x86/pthreadVC2.dll yosys-win32-mxebin-$(YOSYS_VER)/
endif
echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-mxebin-$(YOSYS_VER)/readme.txt
- echo -en 'Documentation at http://www.clifford.at/yosys/.\r\n' >> yosys-win32-mxebin-$(YOSYS_VER)/readme.txt
+ echo -en 'Documentation at https://yosyshq.net/yosys/.\r\n' >> yosys-win32-mxebin-$(YOSYS_VER)/readme.txt
zip -r yosys-win32-mxebin-$(YOSYS_VER).zip yosys-win32-mxebin-$(YOSYS_VER)/
endif
diff --git a/README.md b/README.md
index 203a292d1..0232a5ed0 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
```
yosys -- Yosys Open SYnthesis Suite
-Copyright (C) 2012 - 2020 Claire Wolf <claire@symbioticeda.com>
+Copyright (C) 2012 - 2020 Claire Xenia Wolf <claire@yosyshq.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
@@ -38,13 +38,13 @@ Web Site and Other Resources
============================
More information and documentation can be found on the Yosys web site:
-- http://www.clifford.at/yosys/
+- https://yosyshq.net/yosys/
The "Documentation" page on the web site contains links to more resources,
including a manual that even describes some of the Yosys internals:
-- http://www.clifford.at/yosys/documentation.html
+- https://yosyshq.net/yosys/documentation.html
-The file `CodingReadme` in this directory contains additional information
+The directory `guidelines` contains additional information
for people interested in using the Yosys C++ APIs.
Users interested in formal verification might want to use the formal verification
@@ -53,8 +53,23 @@ front-end for Yosys, SymbiYosys:
- https://github.com/YosysHQ/SymbiYosys
-Setup
-======
+Installation
+============
+
+Yosys is part of the [Tabby CAD Suite](https://www.yosyshq.com/tabby-cad-datasheet) and the [OSS CAD Suite](https://github.com/YosysHQ/oss-cad-suite-build)! The easiest way to use yosys is to install the binary software suite, which contains all required dependencies and related tools.
+
+* [Contact YosysHQ](https://www.yosyshq.com/contact) for a [Tabby CAD Suite](https://www.yosyshq.com/tabby-cad-datasheet) Evaluation License and download link
+* OR go to https://github.com/YosysHQ/oss-cad-suite-build/releases to download the free OSS CAD Suite
+* Follow the [Install Instructions on GitHub](https://github.com/YosysHQ/oss-cad-suite-build#installation)
+
+Make sure to get a Tabby CAD Suite Evaluation License if you need features such as industry-grade SystemVerilog and VHDL parsers!
+
+For more information about the difference between Tabby CAD Suite and the OSS CAD Suite, please visit https://www.yosyshq.com/tabby-cad-datasheet
+
+Many Linux distributions also provide Yosys binaries, some more up to date than others. Check with your package manager!
+
+Building from Source
+====================
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.
@@ -90,10 +105,6 @@ For Cygwin use the following command to install all prerequisites, or select the
setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-devel,make,pkg-config,python3,tcl-devel,boost-build,zlib-devel
-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
-
To configure the build system to use a specific compiler, use one of
$ make config-clang
@@ -489,6 +500,11 @@ Verilog Attributes and non-standard features
for use in blackboxes and whiteboxes. Use ``read_verilog -specify`` to
enable this functionality. (By default these blocks are ignored.)
+- The ``reprocess_after`` internal attribute is used by the Verilog frontend to
+ mark cells with bindings which might depend on the specified instantiated
+ module. Modules with such cells will be reprocessed during the ``hierarchy``
+ pass once the referenced module definition(s) become available.
+
Non-standard or SystemVerilog features for formal verification
==============================================================
@@ -568,7 +584,7 @@ Building the documentation
==========================
Note that there is no need to build the manual if you just want to read it.
-Simply download the PDF from http://www.clifford.at/yosys/documentation.html
+Simply download the PDF from https://yosyshq.net/yosys/documentation.html
instead.
On Ubuntu, texlive needs these packages to be able to build the manual:
diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc
index 476b30488..35935b847 100644
--- a/backends/aiger/aiger.cc
+++ b/backends/aiger/aiger.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc
index 27499b64a..e223f185e 100644
--- a/backends/aiger/xaiger.cc
+++ b/backends/aiger/xaiger.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -156,7 +156,7 @@ struct XAigerWriter
// promote keep wires
for (auto wire : module->wires())
- if (wire->get_bool_attribute(ID::keep) || wire->get_bool_attribute(ID::abc9_keep))
+ if (wire->get_bool_attribute(ID::keep))
sigmap.add(wire);
for (auto wire : module->wires()) {
@@ -177,11 +177,10 @@ struct XAigerWriter
undriven_bits.insert(bit);
unused_bits.insert(bit);
- bool keep = wire->get_bool_attribute(ID::abc9_keep);
- if (wire->port_input || keep)
+ if (wire->port_input)
input_bits.insert(bit);
- keep = keep || wire->get_bool_attribute(ID::keep);
+ bool keep = wire->get_bool_attribute(ID::keep);
if (wire->port_output || keep) {
if (bit != wirebit)
alias_map[wirebit] = bit;
@@ -262,26 +261,27 @@ struct XAigerWriter
if (!timing.count(inst_module->name))
timing.setup_module(inst_module);
- auto &t = timing.at(inst_module->name).arrival;
- for (const auto &conn : cell->connections()) {
- auto port_wire = inst_module->wire(conn.first);
- if (!port_wire->port_output)
+
+ for (auto &i : timing.at(inst_module->name).arrival) {
+ if (!cell->hasPort(i.first.name))
continue;
- for (int i = 0; i < GetSize(conn.second); i++) {
- auto d = t.at(TimingInfo::NameBit(conn.first,i), 0);
- if (d == 0)
- continue;
+ auto port_wire = inst_module->wire(i.first.name);
+ log_assert(port_wire->port_output);
+
+ auto d = i.second.first;
+ if (d == 0)
+ continue;
+ auto offset = i.first.offset;
#ifndef NDEBUG
- if (ys_debug(1)) {
- static std::set<std::tuple<IdString,IdString,int>> seen;
- if (seen.emplace(inst_module->name, conn.first, i).second) log("%s.%s[%d] abc9_arrival = %d\n",
- log_id(cell->type), log_id(conn.first), i, d);
- }
-#endif
- arrival_times[conn.second[i]] = d;
+ if (ys_debug(1)) {
+ static pool<std::pair<IdString,TimingInfo::NameBit>> seen;
+ if (seen.emplace(inst_module->name, i.first).second) log("%s.%s[%d] abc9_arrival = %d\n",
+ log_id(cell->type), log_id(i.first.name), offset, d);
}
+#endif
+ arrival_times[cell->getPort(i.first.name)[offset]] = d;
}
if (abc9_flop)
@@ -432,7 +432,8 @@ struct XAigerWriter
// that has been padded to its full width
if (bit == State::Sx)
continue;
- log_assert(!aig_map.count(bit));
+ if (aig_map.count(bit))
+ log_error("Visited AIG node more than once; this could be a combinatorial loop that has not been broken\n");
aig_map[bit] = 2*aig_m;
}
diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc
index 088819042..ba29d9090 100644
--- a/backends/blif/blif.cc
+++ b/backends/blif/blif.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc
index 692452aad..d62cc4c3d 100644
--- a/backends/btor/btor.cc
+++ b/backends/btor/btor.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -18,7 +18,7 @@
*/
// [[CITE]] Btor2 , BtorMC and Boolector 3.0
-// Aina Niemetz, Mathias Preiner, Clifford Wolf, Armin Biere
+// Aina Niemetz, Mathias Preiner, C. Wolf, Armin Biere
// Computer Aided Verification - 30th International Conference, CAV 2018
// https://cs.stanford.edu/people/niemetz/publication/2018/niemetzpreinerwolfbiere-cav18/
@@ -708,7 +708,7 @@ struct BtorWorker
goto okay;
}
- if (cell->type.in(ID($mem), ID($memrd), ID($memwr), ID($meminit)))
+ if (cell->is_mem_cell())
{
Mem *mem = mem_cells[cell];
@@ -728,10 +728,11 @@ struct BtorWorker
log_error("Memory %s.%s has mixed async/sync write ports.\n",
log_id(module), log_id(mem->memid));
- for (auto &port : mem->rd_ports)
+ for (auto &port : mem->rd_ports) {
if (port.clk_enable)
- log_error("Memory %s.%s has sync read ports.\n",
+ log_error("Memory %s.%s has sync read ports. Please use memory_nordff to convert them first.\n",
log_id(module), log_id(mem->memid));
+ }
int data_sid = get_bv_sid(mem->width);
int bool_sid = get_bv_sid(1);
@@ -864,7 +865,7 @@ struct BtorWorker
log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_btor`.\n",
log_id(cell->type), log_id(module), log_id(cell));
}
- if (cell->type.in(ID($adff), ID($adffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF") {
+ if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") {
log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_btor`.\n",
log_id(cell->type), log_id(module), log_id(cell));
}
@@ -1080,10 +1081,12 @@ struct BtorWorker
memories = Mem::get_all_memories(module);
dict<IdString, Mem*> mem_dict;
- for (auto &mem : memories)
+ for (auto &mem : memories) {
+ mem.narrow();
mem_dict[mem.memid] = &mem;
+ }
for (auto cell : module->cells())
- if (cell->type.in(ID($mem), ID($memwr), ID($memrd), ID($meminit)))
+ if (cell->is_mem_cell())
mem_cells[cell] = mem_dict[cell->parameters.at(ID::MEMID).decode_string()];
btorf_push("inputs");
@@ -1396,6 +1399,11 @@ struct BtorBackend : public Backend {
log_header(design, "Executing BTOR backend.\n");
+ log_push();
+ Pass::call(design, "bmuxmap");
+ Pass::call(design, "demuxmap");
+ log_pop();
+
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h
index 0e55c46c2..b4ffa87cd 100644
--- a/backends/cxxrtl/cxxrtl.h
+++ b/backends/cxxrtl/cxxrtl.h
@@ -457,6 +457,42 @@ struct value : public expr_base<value<Bits>> {
return shr<AmountBits, /*Signed=*/true>(amount);
}
+ template<size_t ResultBits, size_t SelBits>
+ value<ResultBits> bmux(const value<SelBits> &sel) const {
+ static_assert(ResultBits << SelBits == Bits, "invalid sizes used in bmux()");
+ size_t amount = sel.data[0] * ResultBits;
+ size_t shift_chunks = amount / chunk::bits;
+ size_t shift_bits = amount % chunk::bits;
+ value<ResultBits> result;
+ chunk::type carry = 0;
+ if (ResultBits % chunk::bits + shift_bits > chunk::bits)
+ carry = data[result.chunks + shift_chunks] << (chunk::bits - shift_bits);
+ for (size_t n = 0; n < result.chunks; n++) {
+ result.data[result.chunks - 1 - n] = carry | (data[result.chunks + shift_chunks - 1 - n] >> shift_bits);
+ carry = (shift_bits == 0) ? 0
+ : data[result.chunks + shift_chunks - 1 - n] << (chunk::bits - shift_bits);
+ }
+ return result;
+ }
+
+ template<size_t ResultBits, size_t SelBits>
+ value<ResultBits> demux(const value<SelBits> &sel) const {
+ static_assert(Bits << SelBits == ResultBits, "invalid sizes used in demux()");
+ size_t amount = sel.data[0] * Bits;
+ size_t shift_chunks = amount / chunk::bits;
+ size_t shift_bits = amount % chunk::bits;
+ value<ResultBits> result;
+ chunk::type carry = 0;
+ for (size_t n = 0; n < chunks; n++) {
+ result.data[shift_chunks + n] = (data[n] << shift_bits) | carry;
+ carry = (shift_bits == 0) ? 0
+ : data[n] >> (chunk::bits - shift_bits);
+ }
+ if (Bits % chunk::bits + shift_bits > chunk::bits)
+ result.data[shift_chunks + chunks] = carry;
+ return result;
+ }
+
size_t ctpop() const {
size_t count = 0;
for (size_t n = 0; n < chunks; n++) {
@@ -722,50 +758,32 @@ std::ostream &operator<<(std::ostream &os, const wire<Bits> &val) {
template<size_t Width>
struct memory {
- std::vector<value<Width>> data;
+ const size_t depth;
+ std::unique_ptr<value<Width>[]> data;
- size_t depth() const {
- return data.size();
- }
-
- memory() = delete;
- explicit memory(size_t depth) : data(depth) {}
+ explicit memory(size_t depth) : depth(depth), data(new value<Width>[depth]) {}
memory(const memory<Width> &) = delete;
memory<Width> &operator=(const memory<Width> &) = delete;
memory(memory<Width> &&) = default;
- memory<Width> &operator=(memory<Width> &&) = default;
-
- // The only way to get the compiler to put the initializer in .rodata and do not copy it on stack is to stuff it
- // into a plain array. You'd think an std::initializer_list would work here, but it doesn't, because you can't
- // construct an initializer_list in a constexpr (or something) and so if you try to do that the whole thing is
- // first copied on the stack (probably overflowing it) and then again into `data`.
- template<size_t Size>
- struct init {
- size_t offset;
- value<Width> data[Size];
- };
-
- template<size_t... InitSize>
- explicit memory(size_t depth, const init<InitSize> &...init) : data(depth) {
- data.resize(depth);
- // This utterly reprehensible construct is the most reasonable way to apply a function to every element
- // of a parameter pack, if the elements all have different types and so cannot be cast to an initializer list.
- auto _ = {std::move(std::begin(init.data), std::end(init.data), data.begin() + init.offset)...};
- (void)_;
+ memory<Width> &operator=(memory<Width> &&other) {
+ assert(depth == other.depth);
+ data = std::move(other.data);
+ write_queue = std::move(other.write_queue);
+ return *this;
}
// An operator for direct memory reads. May be used at any time during the simulation.
const value<Width> &operator [](size_t index) const {
- assert(index < data.size());
+ assert(index < depth);
return data[index];
}
// An operator for direct memory writes. May only be used before the simulation is started. If used
// after the simulation is started, the design may malfunction.
value<Width> &operator [](size_t index) {
- assert(index < data.size());
+ assert(index < depth);
return data[index];
}
@@ -790,7 +808,7 @@ struct memory {
std::vector<write> write_queue;
void update(size_t index, const value<Width> &val, const value<Width> &mask, int priority = 0) {
- assert(index < data.size());
+ assert(index < depth);
// Queue up the write while keeping the queue sorted by priority.
write_queue.insert(
std::upper_bound(write_queue.begin(), write_queue.end(), priority,
@@ -947,9 +965,9 @@ struct debug_item : ::cxxrtl_object {
flags = 0;
width = Width;
lsb_at = 0;
- depth = item.data.size();
+ depth = item.depth;
zero_at = zero_offset;
- curr = item.data.empty() ? nullptr : item.data[0].data;
+ curr = item.data ? item.data[0].data : nullptr;
next = nullptr;
outline = nullptr;
}
@@ -999,6 +1017,22 @@ struct debug_item : ::cxxrtl_object {
next = nullptr;
outline = &group;
}
+
+ template<size_t Bits, class IntegerT>
+ IntegerT get() const {
+ assert(width == Bits && depth == 1);
+ value<Bits> item;
+ std::copy(curr, curr + value<Bits>::chunks, item.data);
+ return item.template get<IntegerT>();
+ }
+
+ template<size_t Bits, class IntegerT>
+ void set(IntegerT other) const {
+ assert(width == Bits && depth == 1);
+ value<Bits> item;
+ item.template set<IntegerT>(other);
+ std::copy(item.data, item.data + value<Bits>::chunks, next);
+ }
};
static_assert(std::is_standard_layout<debug_item>::value, "debug_item is not compatible with C layout");
@@ -1035,9 +1069,9 @@ struct debug_items {
}
};
-// Tag class to disambiguate module move constructor and module constructor that takes black boxes
-// out of another instance of the module.
-struct adopt {};
+// Tag class to disambiguate the default constructor used by the toplevel module that calls reset(),
+// and the constructor of interior modules that should not call it.
+struct interior {};
struct module {
module() {}
diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc
index 39046bd78..404755b1e 100644
--- a/backends/cxxrtl/cxxrtl_backend.cc
+++ b/backends/cxxrtl/cxxrtl_backend.cc
@@ -198,7 +198,7 @@ bool is_extending_cell(RTLIL::IdString type)
bool is_inlinable_cell(RTLIL::IdString type)
{
return is_unary_cell(type) || is_binary_cell(type) || type.in(
- ID($mux), ID($concat), ID($slice), ID($pmux));
+ ID($mux), ID($concat), ID($slice), ID($pmux), ID($bmux), ID($demux));
}
bool is_ff_cell(RTLIL::IdString type)
@@ -206,6 +206,7 @@ bool is_ff_cell(RTLIL::IdString type)
return type.in(
ID($dff), ID($dffe), ID($sdff), ID($sdffe), ID($sdffce),
ID($adff), ID($adffe), ID($dffsr), ID($dffsre),
+ ID($aldff), ID($aldffe),
ID($dlatch), ID($adlatch), ID($dlatchsr), ID($sr));
}
@@ -216,7 +217,7 @@ bool is_internal_cell(RTLIL::IdString type)
bool is_effectful_cell(RTLIL::IdString type)
{
- return type == ID($memwr) || type.isPublic();
+ return type.isPublic();
}
bool is_cxxrtl_blackbox_cell(const RTLIL::Cell *cell)
@@ -226,6 +227,14 @@ bool is_cxxrtl_blackbox_cell(const RTLIL::Cell *cell)
return cell_module->get_bool_attribute(ID(cxxrtl_blackbox));
}
+bool is_memwr_process(const RTLIL::Process *process)
+{
+ for (auto sync : process->syncs)
+ if (!sync->mem_write_actions.empty())
+ return true;
+ return false;
+}
+
enum class CxxrtlPortType {
UNKNOWN = 0, // or mixed comb/sync
COMB = 1,
@@ -274,12 +283,16 @@ struct FlowGraph {
CELL_EVAL,
PROCESS_SYNC,
PROCESS_CASE,
+ MEM_RDPORT,
+ MEM_WRPORTS,
};
Type type;
RTLIL::SigSig connect = {};
- const RTLIL::Cell *cell = NULL;
- const RTLIL::Process *process = NULL;
+ const RTLIL::Cell *cell = nullptr;
+ const RTLIL::Process *process = nullptr;
+ const Mem *mem = nullptr;
+ int portidx;
};
std::vector<Node*> nodes;
@@ -314,8 +327,14 @@ struct FlowGraph {
for (auto bit : sig.bits())
bit_has_state[bit] |= is_ff;
// Only comb defs of an entire wire in the right order can be inlined.
- if (!is_ff && sig.is_wire())
- wire_def_inlinable[sig.as_wire()] = inlinable;
+ if (!is_ff && sig.is_wire()) {
+ // Only a single def of a wire can be inlined. (Multiple defs of a wire are unsound, but we
+ // handle them anyway to avoid assertion failures later.)
+ if (!wire_def_inlinable.count(sig.as_wire()))
+ wire_def_inlinable[sig.as_wire()] = inlinable;
+ else
+ wire_def_inlinable[sig.as_wire()] = false;
+ }
}
void add_uses(Node *node, const RTLIL::SigSpec &sig)
@@ -414,7 +433,7 @@ struct FlowGraph {
if (cell->output(conn.first)) {
if (is_inlinable_cell(cell->type))
add_defs(node, conn.second, /*is_ff=*/false, /*inlinable=*/true);
- else if (is_ff_cell(cell->type) || (cell->type == ID($memrd) && cell->getParam(ID::CLK_ENABLE).as_bool()))
+ else if (is_ff_cell(cell->type))
add_defs(node, conn.second, /*is_ff=*/true, /*inlinable=*/false);
else if (is_internal_cell(cell->type))
add_defs(node, conn.second, /*is_ff=*/false, /*inlinable=*/false);
@@ -477,14 +496,20 @@ struct FlowGraph {
void add_sync_rules_defs_uses(Node *node, const RTLIL::Process *process)
{
- for (auto sync : process->syncs)
- for (auto action : sync->actions) {
+ for (auto sync : process->syncs) {
+ for (auto &action : sync->actions) {
if (sync->type == RTLIL::STp || sync->type == RTLIL::STn || sync->type == RTLIL::STe)
- add_defs(node, action.first, /*is_ff=*/true, /*inlinable=*/false);
+ add_defs(node, action.first, /*is_ff=*/true, /*inlinable=*/false);
else
add_defs(node, action.first, /*is_ff=*/false, /*inlinable=*/false);
add_uses(node, action.second);
}
+ for (auto &memwr : sync->mem_write_actions) {
+ add_uses(node, memwr.address);
+ add_uses(node, memwr.data);
+ add_uses(node, memwr.enable);
+ }
+ }
}
Node *add_node(const RTLIL::Process *process)
@@ -502,6 +527,51 @@ struct FlowGraph {
add_case_rule_defs_uses(node, &process->root_case);
return node;
}
+
+ // Memories
+ void add_node(const Mem *mem) {
+ for (int i = 0; i < GetSize(mem->rd_ports); i++) {
+ auto &port = mem->rd_ports[i];
+ Node *node = new Node;
+ node->type = Node::Type::MEM_RDPORT;
+ node->mem = mem;
+ node->portidx = i;
+ nodes.push_back(node);
+ add_defs(node, port.data, /*is_ff=*/port.clk_enable, /*inlinable=*/false);
+ add_uses(node, port.clk);
+ add_uses(node, port.en);
+ add_uses(node, port.arst);
+ add_uses(node, port.srst);
+ add_uses(node, port.addr);
+ bool transparent = false;
+ for (int j = 0; j < GetSize(mem->wr_ports); j++) {
+ auto &wrport = mem->wr_ports[j];
+ if (port.transparency_mask[j]) {
+ // Our implementation of transparent read ports reads en, addr and data from every write port
+ // the read port is transparent with.
+ add_uses(node, wrport.en);
+ add_uses(node, wrport.addr);
+ add_uses(node, wrport.data);
+ transparent = true;
+ }
+ }
+ // Also we read the read address twice in this case (prevent inlining).
+ if (transparent)
+ add_uses(node, port.addr);
+ }
+ if (!mem->wr_ports.empty()) {
+ Node *node = new Node;
+ node->type = Node::Type::MEM_WRPORTS;
+ node->mem = mem;
+ nodes.push_back(node);
+ for (auto &port : mem->wr_ports) {
+ add_uses(node, port.clk);
+ add_uses(node, port.en);
+ add_uses(node, port.addr);
+ add_uses(node, port.data);
+ }
+ }
+ }
};
std::vector<std::string> split_by(const std::string &str, const std::string &sep)
@@ -614,6 +684,8 @@ struct CxxrtlWorker {
std::ostream *impl_f = nullptr;
std::ostream *intf_f = nullptr;
+ bool print_wire_types = false;
+ bool print_debug_wire_types = false;
bool run_hierarchy = false;
bool run_flatten = false;
bool run_proc = false;
@@ -635,10 +707,11 @@ struct CxxrtlWorker {
int temporary = 0;
dict<const RTLIL::Module*, SigMap> sigmaps;
+ dict<const RTLIL::Module*, std::vector<Mem>> mod_memories;
+ pool<std::pair<const RTLIL::Module*, RTLIL::IdString>> writable_memories;
pool<const RTLIL::Wire*> edge_wires;
+ dict<const RTLIL::Wire*, RTLIL::Const> wire_init;
dict<RTLIL::SigBit, RTLIL::SyncType> edge_types;
- pool<const RTLIL::Memory*> writable_memories;
- dict<const RTLIL::Cell*, pool<const RTLIL::Cell*>> transparent_for;
dict<const RTLIL::Module*, std::vector<FlowGraph::Node>> schedule, debug_schedule;
dict<const RTLIL::Wire*, WireType> wire_types, debug_wire_types;
dict<RTLIL::SigBit, bool> bit_has_state;
@@ -722,6 +795,11 @@ struct CxxrtlWorker {
return mangle_module_name(module->name, /*is_blackbox=*/module->get_bool_attribute(ID(cxxrtl_blackbox)));
}
+ std::string mangle(const Mem *mem)
+ {
+ return mangle_memory_name(mem->memid);
+ }
+
std::string mangle(const RTLIL::Memory *memory)
{
return mangle_memory_name(memory->name);
@@ -856,11 +934,6 @@ struct CxxrtlWorker {
f << "}";
}
- void dump_const_init(const RTLIL::Const &data)
- {
- dump_const_init(data, data.size());
- }
-
void dump_const(const RTLIL::Const &data, int width, int offset = 0, bool fixed_width = false)
{
f << "value<" << width << ">";
@@ -1081,6 +1154,22 @@ struct CxxrtlWorker {
for (int part = 0; part < s_width; part++) {
f << ")";
}
+ // Big muxes
+ } else if (cell->type == ID($bmux)) {
+ dump_sigspec_rhs(cell->getPort(ID::A), for_debug);
+ f << ".bmux<";
+ f << cell->getParam(ID::WIDTH).as_int();
+ f << ">(";
+ dump_sigspec_rhs(cell->getPort(ID::S), for_debug);
+ f << ").val()";
+ // Demuxes
+ } else if (cell->type == ID($demux)) {
+ dump_sigspec_rhs(cell->getPort(ID::A), for_debug);
+ f << ".demux<";
+ f << GetSize(cell->getPort(ID::Y));
+ f << ">(";
+ dump_sigspec_rhs(cell->getPort(ID::S), for_debug);
+ f << ").val()";
// Concats
} else if (cell->type == ID($concat)) {
dump_sigspec_rhs(cell->getPort(ID::B), for_debug);
@@ -1190,6 +1279,20 @@ struct CxxrtlWorker {
dec_indent();
f << indent << "}\n";
}
+ if (cell->hasPort(ID::ALOAD)) {
+ // Asynchronous load
+ f << indent << "if (";
+ dump_sigspec_rhs(cell->getPort(ID::ALOAD));
+ f << " == value<1> {" << cell->getParam(ID::ALOAD_POLARITY).as_bool() << "u}) {\n";
+ inc_indent();
+ f << indent;
+ dump_sigspec_lhs(cell->getPort(ID::Q));
+ f << " = ";
+ dump_sigspec_rhs(cell->getPort(ID::AD));
+ f << ";\n";
+ dec_indent();
+ f << indent << "}\n";
+ }
if (cell->hasPort(ID::SET)) {
// Asynchronous set (for individual bits)
f << indent;
@@ -1214,112 +1317,6 @@ struct CxxrtlWorker {
dump_sigspec_rhs(cell->getPort(ID::CLR));
f << (cell->getParam(ID::CLR_POLARITY).as_bool() ? "" : ".bit_not()") << ");\n";
}
- // Memory ports
- } else if (cell->type.in(ID($memrd), ID($memwr))) {
- if (cell->getParam(ID::CLK_ENABLE).as_bool()) {
- log_assert(!for_debug);
- RTLIL::SigBit clk_bit = cell->getPort(ID::CLK)[0];
- clk_bit = sigmaps[clk_bit.wire->module](clk_bit);
- if (clk_bit.wire) {
- f << indent << "if (" << (cell->getParam(ID::CLK_POLARITY).as_bool() ? "posedge_" : "negedge_")
- << mangle(clk_bit) << ") {\n";
- } else {
- f << indent << "if (false) {\n";
- }
- inc_indent();
- }
- RTLIL::Memory *memory = cell->module->memories[cell->getParam(ID::MEMID).decode_string()];
- std::string valid_index_temp = fresh_temporary();
- f << indent << "auto " << valid_index_temp << " = memory_index(";
- dump_sigspec_rhs(cell->getPort(ID::ADDR));
- f << ", " << memory->start_offset << ", " << memory->size << ");\n";
- if (cell->type == ID($memrd)) {
- bool has_enable = cell->getParam(ID::CLK_ENABLE).as_bool() && !cell->getPort(ID::EN).is_fully_ones();
- if (has_enable) {
- f << indent << "if (";
- dump_sigspec_rhs(cell->getPort(ID::EN));
- f << ") {\n";
- inc_indent();
- }
- // The generated code has two bounds checks; one in an assertion, and another that guards the read.
- // This is done so that the code does not invoke undefined behavior under any conditions, but nevertheless
- // loudly crashes if an illegal condition is encountered. The assert may be turned off with -DCXXRTL_NDEBUG
- // not only for release builds, but also to make sure the simulator (which is presumably embedded in some
- // larger program) will never crash the code that calls into it.
- //
- // If assertions are disabled, out of bounds reads are defined to return zero.
- f << indent << "CXXRTL_ASSERT(" << valid_index_temp << ".valid && \"out of bounds read\");\n";
- f << indent << "if(" << valid_index_temp << ".valid) {\n";
- inc_indent();
- if (writable_memories[memory]) {
- std::string lhs_temp = fresh_temporary();
- f << indent << "value<" << memory->width << "> " << lhs_temp << " = "
- << mangle(memory) << "[" << valid_index_temp << ".index];\n";
- std::vector<const RTLIL::Cell*> memwr_cells(transparent_for[cell].begin(), transparent_for[cell].end());
- if (!memwr_cells.empty()) {
- std::string addr_temp = fresh_temporary();
- f << indent << "const value<" << cell->getPort(ID::ADDR).size() << "> &" << addr_temp << " = ";
- dump_sigspec_rhs(cell->getPort(ID::ADDR));
- f << ";\n";
- std::sort(memwr_cells.begin(), memwr_cells.end(),
- [](const RTLIL::Cell *a, const RTLIL::Cell *b) {
- return a->getParam(ID::PRIORITY).as_int() < b->getParam(ID::PRIORITY).as_int();
- });
- for (auto memwr_cell : memwr_cells) {
- f << indent << "if (" << addr_temp << " == ";
- dump_sigspec_rhs(memwr_cell->getPort(ID::ADDR));
- f << ") {\n";
- inc_indent();
- f << indent << lhs_temp << " = " << lhs_temp;
- f << ".update(";
- dump_sigspec_rhs(memwr_cell->getPort(ID::DATA));
- f << ", ";
- dump_sigspec_rhs(memwr_cell->getPort(ID::EN));
- f << ");\n";
- dec_indent();
- f << indent << "}\n";
- }
- }
- f << indent;
- dump_sigspec_lhs(cell->getPort(ID::DATA));
- f << " = " << lhs_temp << ";\n";
- } else {
- f << indent;
- dump_sigspec_lhs(cell->getPort(ID::DATA));
- f << " = " << mangle(memory) << "[" << valid_index_temp << ".index];\n";
- }
- dec_indent();
- f << indent << "} else {\n";
- inc_indent();
- f << indent;
- dump_sigspec_lhs(cell->getPort(ID::DATA));
- f << " = value<" << memory->width << "> {};\n";
- dec_indent();
- f << indent << "}\n";
- if (has_enable) {
- dec_indent();
- f << indent << "}\n";
- }
- } else /*if (cell->type == ID($memwr))*/ {
- log_assert(writable_memories[memory]);
- // See above for rationale of having both the assert and the condition.
- //
- // If assertions are disabled, out of bounds writes are defined to do nothing.
- f << indent << "CXXRTL_ASSERT(" << valid_index_temp << ".valid && \"out of bounds write\");\n";
- f << indent << "if (" << valid_index_temp << ".valid) {\n";
- inc_indent();
- f << indent << mangle(memory) << ".update(" << valid_index_temp << ".index, ";
- dump_sigspec_rhs(cell->getPort(ID::DATA));
- f << ", ";
- dump_sigspec_rhs(cell->getPort(ID::EN));
- f << ", " << cell->getParam(ID::PRIORITY).as_int() << ");\n";
- dec_indent();
- f << indent << "}\n";
- }
- if (cell->getParam(ID::CLK_ENABLE).as_bool()) {
- dec_indent();
- f << indent << "}\n";
- }
// Internal cells
} else if (is_internal_cell(cell->type)) {
log_cmd_error("Unsupported internal cell `%s'.\n", cell->type.c_str());
@@ -1332,7 +1329,7 @@ struct CxxrtlWorker {
for (auto conn : cell->connections())
if (cell->input(conn.first)) {
RTLIL::Module *cell_module = cell->module->design->module(cell->type);
- log_assert(cell_module != nullptr && cell_module->wire(conn.first) && conn.second.is_wire());
+ log_assert(cell_module != nullptr && cell_module->wire(conn.first));
RTLIL::Wire *cell_module_wire = cell_module->wire(conn.first);
f << indent << mangle(cell) << access << mangle_wire_name(conn.first);
if (!is_cxxrtl_blackbox_cell(cell) && wire_types[cell_module_wire].is_buffered()) {
@@ -1342,7 +1339,7 @@ struct CxxrtlWorker {
f << " = ";
dump_sigspec_rhs(conn.second);
f << ";\n";
- if (getenv("CXXRTL_VOID_MY_WARRANTY")) {
+ if (getenv("CXXRTL_VOID_MY_WARRANTY") && conn.second.is_wire()) {
// Until we have proper clock tree detection, this really awful hack that opportunistically
// propagates prev_* values for clocks can be used to estimate how much faster a design could
// be if only one clock edge was simulated by replacing:
@@ -1411,30 +1408,30 @@ struct CxxrtlWorker {
collect_sigspec_rhs(port.second, for_debug, cells);
}
- void dump_assign(const RTLIL::SigSig &sigsig)
+ void dump_assign(const RTLIL::SigSig &sigsig, bool for_debug = false)
{
f << indent;
- dump_sigspec_lhs(sigsig.first);
+ dump_sigspec_lhs(sigsig.first, for_debug);
f << " = ";
- dump_sigspec_rhs(sigsig.second);
+ dump_sigspec_rhs(sigsig.second, for_debug);
f << ";\n";
}
- void dump_case_rule(const RTLIL::CaseRule *rule)
+ void dump_case_rule(const RTLIL::CaseRule *rule, bool for_debug = false)
{
for (auto action : rule->actions)
- dump_assign(action);
+ dump_assign(action, for_debug);
for (auto switch_ : rule->switches)
- dump_switch_rule(switch_);
+ dump_switch_rule(switch_, for_debug);
}
- void dump_switch_rule(const RTLIL::SwitchRule *rule)
+ void dump_switch_rule(const RTLIL::SwitchRule *rule, bool for_debug = false)
{
// The switch attributes are printed before the switch condition is captured.
dump_attrs(rule);
std::string signal_temp = fresh_temporary();
f << indent << "const value<" << rule->signal.size() << "> &" << signal_temp << " = ";
- dump_sigspec(rule->signal, /*is_lhs=*/false);
+ dump_sigspec(rule->signal, /*is_lhs=*/false, for_debug);
f << ";\n";
bool first = true;
@@ -1454,7 +1451,7 @@ struct CxxrtlWorker {
first = false;
if (compare.is_fully_def()) {
f << signal_temp << " == ";
- dump_sigspec(compare, /*is_lhs=*/false);
+ dump_sigspec(compare, /*is_lhs=*/false, for_debug);
} else if (compare.is_fully_const()) {
RTLIL::Const compare_mask, compare_value;
for (auto bit : compare.as_const()) {
@@ -1488,30 +1485,34 @@ struct CxxrtlWorker {
}
f << "{\n";
inc_indent();
- dump_case_rule(case_);
+ dump_case_rule(case_, for_debug);
dec_indent();
}
f << indent << "}\n";
}
- void dump_process_case(const RTLIL::Process *proc)
+ void dump_process_case(const RTLIL::Process *proc, bool for_debug = false)
{
dump_attrs(proc);
f << indent << "// process " << proc->name.str() << " case\n";
// The case attributes (for root case) are always empty.
log_assert(proc->root_case.attributes.empty());
- dump_case_rule(&proc->root_case);
+ dump_case_rule(&proc->root_case, for_debug);
}
- void dump_process_syncs(const RTLIL::Process *proc)
+ void dump_process_syncs(const RTLIL::Process *proc, bool for_debug = false)
{
dump_attrs(proc);
f << indent << "// process " << proc->name.str() << " syncs\n";
for (auto sync : proc->syncs) {
+ log_assert(!for_debug || sync->type == RTLIL::STa);
+
RTLIL::SigBit sync_bit;
if (!sync->signal.empty()) {
sync_bit = sync->signal[0];
sync_bit = sigmaps[sync_bit.wire->module](sync_bit);
+ if (!sync_bit.is_wire())
+ continue; // a clock, or more commonly a reset, can be tied to a constant driver
}
pool<std::string> events;
@@ -1551,8 +1552,224 @@ struct CxxrtlWorker {
}
f << ") {\n";
inc_indent();
- for (auto action : sync->actions)
- dump_assign(action);
+ for (auto &action : sync->actions)
+ dump_assign(action, for_debug);
+ for (auto &memwr : sync->mem_write_actions) {
+ RTLIL::Memory *memory = proc->module->memories.at(memwr.memid);
+ std::string valid_index_temp = fresh_temporary();
+ f << indent << "auto " << valid_index_temp << " = memory_index(";
+ dump_sigspec_rhs(memwr.address);
+ f << ", " << memory->start_offset << ", " << memory->size << ");\n";
+ // See below for rationale of having both the assert and the condition.
+ //
+ // If assertions are disabled, out of bounds writes are defined to do nothing.
+ f << indent << "CXXRTL_ASSERT(" << valid_index_temp << ".valid && \"out of bounds write\");\n";
+ f << indent << "if (" << valid_index_temp << ".valid) {\n";
+ inc_indent();
+ f << indent << mangle(memory) << ".update(" << valid_index_temp << ".index, ";
+ dump_sigspec_rhs(memwr.data);
+ f << ", ";
+ dump_sigspec_rhs(memwr.enable);
+ f << ");\n";
+ dec_indent();
+ f << indent << "}\n";
+ }
+ dec_indent();
+ f << indent << "}\n";
+ }
+ }
+ }
+
+ void dump_mem_rdport(const Mem *mem, int portidx, bool for_debug = false)
+ {
+ auto &port = mem->rd_ports[portidx];
+ dump_attrs(&port);
+ f << indent << "// memory " << mem->memid.str() << " read port " << portidx << "\n";
+ if (port.clk_enable) {
+ log_assert(!for_debug);
+ RTLIL::SigBit clk_bit = port.clk[0];
+ clk_bit = sigmaps[clk_bit.wire->module](clk_bit);
+ if (clk_bit.wire) {
+ f << indent << "if (" << (port.clk_polarity ? "posedge_" : "negedge_")
+ << mangle(clk_bit) << ") {\n";
+ } else {
+ f << indent << "if (false) {\n";
+ }
+ inc_indent();
+ }
+ std::vector<const RTLIL::Cell*> inlined_cells_addr;
+ collect_sigspec_rhs(port.addr, for_debug, inlined_cells_addr);
+ if (!inlined_cells_addr.empty())
+ dump_inlined_cells(inlined_cells_addr);
+ std::string valid_index_temp = fresh_temporary();
+ f << indent << "auto " << valid_index_temp << " = memory_index(";
+ // Almost all non-elidable cells cannot appear in debug_eval(), but $memrd is an exception; asynchronous
+ // memory read ports can.
+ dump_sigspec_rhs(port.addr, for_debug);
+ f << ", " << mem->start_offset << ", " << mem->size << ");\n";
+ bool has_enable = port.clk_enable && !port.en.is_fully_ones();
+ if (has_enable) {
+ std::vector<const RTLIL::Cell*> inlined_cells_en;
+ collect_sigspec_rhs(port.en, for_debug, inlined_cells_en);
+ if (!inlined_cells_en.empty())
+ dump_inlined_cells(inlined_cells_en);
+ f << indent << "if (";
+ dump_sigspec_rhs(port.en);
+ f << ") {\n";
+ inc_indent();
+ }
+ // The generated code has two bounds checks; one in an assertion, and another that guards the read.
+ // This is done so that the code does not invoke undefined behavior under any conditions, but nevertheless
+ // loudly crashes if an illegal condition is encountered. The assert may be turned off with -DCXXRTL_NDEBUG
+ // not only for release builds, but also to make sure the simulator (which is presumably embedded in some
+ // larger program) will never crash the code that calls into it.
+ //
+ // If assertions are disabled, out of bounds reads are defined to return zero.
+ f << indent << "CXXRTL_ASSERT(" << valid_index_temp << ".valid && \"out of bounds read\");\n";
+ f << indent << "if(" << valid_index_temp << ".valid) {\n";
+ inc_indent();
+ if (!mem->wr_ports.empty()) {
+ std::string lhs_temp = fresh_temporary();
+ f << indent << "value<" << mem->width << "> " << lhs_temp << " = "
+ << mangle(mem) << "[" << valid_index_temp << ".index];\n";
+ bool transparent = false;
+ for (auto bit : port.transparency_mask)
+ if (bit)
+ transparent = true;
+ if (transparent) {
+ std::string addr_temp = fresh_temporary();
+ f << indent << "const value<" << port.addr.size() << "> &" << addr_temp << " = ";
+ dump_sigspec_rhs(port.addr);
+ f << ";\n";
+ for (int i = 0; i < GetSize(mem->wr_ports); i++) {
+ auto &wrport = mem->wr_ports[i];
+ if (!port.transparency_mask[i])
+ continue;
+ f << indent << "if (" << addr_temp << " == ";
+ dump_sigspec_rhs(wrport.addr);
+ f << ") {\n";
+ inc_indent();
+ f << indent << lhs_temp << " = " << lhs_temp;
+ f << ".update(";
+ dump_sigspec_rhs(wrport.data);
+ f << ", ";
+ dump_sigspec_rhs(wrport.en);
+ f << ");\n";
+ dec_indent();
+ f << indent << "}\n";
+ }
+ }
+ f << indent;
+ dump_sigspec_lhs(port.data);
+ f << " = " << lhs_temp << ";\n";
+ } else {
+ f << indent;
+ dump_sigspec_lhs(port.data);
+ f << " = " << mangle(mem) << "[" << valid_index_temp << ".index];\n";
+ }
+ dec_indent();
+ f << indent << "} else {\n";
+ inc_indent();
+ f << indent;
+ dump_sigspec_lhs(port.data);
+ f << " = value<" << mem->width << "> {};\n";
+ dec_indent();
+ f << indent << "}\n";
+ if (has_enable && !port.ce_over_srst) {
+ dec_indent();
+ f << indent << "}\n";
+ }
+ if (port.srst != State::S0) {
+ // Synchronous reset
+ std::vector<const RTLIL::Cell*> inlined_cells_srst;
+ collect_sigspec_rhs(port.srst, for_debug, inlined_cells_srst);
+ if (!inlined_cells_srst.empty())
+ dump_inlined_cells(inlined_cells_srst);
+ f << indent << "if (";
+ dump_sigspec_rhs(port.srst);
+ f << " == value<1> {1u}) {\n";
+ inc_indent();
+ f << indent;
+ dump_sigspec_lhs(port.data);
+ f << " = ";
+ dump_const(port.srst_value);
+ f << ";\n";
+ dec_indent();
+ f << indent << "}\n";
+ }
+ if (has_enable && port.ce_over_srst) {
+ dec_indent();
+ f << indent << "}\n";
+ }
+ if (port.clk_enable) {
+ dec_indent();
+ f << indent << "}\n";
+ }
+ if (port.arst != State::S0) {
+ // Asynchronous reset
+ std::vector<const RTLIL::Cell*> inlined_cells_arst;
+ collect_sigspec_rhs(port.arst, for_debug, inlined_cells_arst);
+ if (!inlined_cells_arst.empty())
+ dump_inlined_cells(inlined_cells_arst);
+ f << indent << "if (";
+ dump_sigspec_rhs(port.arst);
+ f << " == value<1> {1u}) {\n";
+ inc_indent();
+ f << indent;
+ dump_sigspec_lhs(port.data);
+ f << " = ";
+ dump_const(port.arst_value);
+ f << ";\n";
+ dec_indent();
+ f << indent << "}\n";
+ }
+ }
+
+ void dump_mem_wrports(const Mem *mem, bool for_debug = false)
+ {
+ log_assert(!for_debug);
+ for (int portidx = 0; portidx < GetSize(mem->wr_ports); portidx++) {
+ auto &port = mem->wr_ports[portidx];
+ dump_attrs(&port);
+ f << indent << "// memory " << mem->memid.str() << " write port " << portidx << "\n";
+ if (port.clk_enable) {
+ RTLIL::SigBit clk_bit = port.clk[0];
+ clk_bit = sigmaps[clk_bit.wire->module](clk_bit);
+ if (clk_bit.wire) {
+ f << indent << "if (" << (port.clk_polarity ? "posedge_" : "negedge_")
+ << mangle(clk_bit) << ") {\n";
+ } else {
+ f << indent << "if (false) {\n";
+ }
+ inc_indent();
+ }
+ std::vector<const RTLIL::Cell*> inlined_cells_addr;
+ collect_sigspec_rhs(port.addr, for_debug, inlined_cells_addr);
+ if (!inlined_cells_addr.empty())
+ dump_inlined_cells(inlined_cells_addr);
+ std::string valid_index_temp = fresh_temporary();
+ f << indent << "auto " << valid_index_temp << " = memory_index(";
+ dump_sigspec_rhs(port.addr);
+ f << ", " << mem->start_offset << ", " << mem->size << ");\n";
+ // See above for rationale of having both the assert and the condition.
+ //
+ // If assertions are disabled, out of bounds writes are defined to do nothing.
+ f << indent << "CXXRTL_ASSERT(" << valid_index_temp << ".valid && \"out of bounds write\");\n";
+ f << indent << "if (" << valid_index_temp << ".valid) {\n";
+ inc_indent();
+ std::vector<const RTLIL::Cell*> inlined_cells;
+ collect_sigspec_rhs(port.data, for_debug, inlined_cells);
+ collect_sigspec_rhs(port.en, for_debug, inlined_cells);
+ if (!inlined_cells.empty())
+ dump_inlined_cells(inlined_cells);
+ f << indent << mangle(mem) << ".update(" << valid_index_temp << ".index, ";
+ dump_sigspec_rhs(port.data);
+ f << ", ";
+ dump_sigspec_rhs(port.en);
+ f << ", " << portidx << ");\n";
+ dec_indent();
+ f << indent << "}\n";
+ if (port.clk_enable) {
dec_indent();
f << indent << "}\n";
}
@@ -1579,20 +1796,10 @@ struct CxxrtlWorker {
} else {
f << "<" << wire->width << ">";
}
- f << " " << mangle(wire);
- if (wire->has_attribute(ID::init)) {
- f << " ";
- dump_const_init(wire->attributes.at(ID::init));
- }
- f << ";\n";
+ f << " " << mangle(wire) << ";\n";
if (edge_wires[wire]) {
if (!wire_type.is_buffered()) {
- f << indent << "value<" << wire->width << "> prev_" << mangle(wire);
- if (wire->has_attribute(ID::init)) {
- f << " ";
- dump_const_init(wire->attributes.at(ID::init));
- }
- f << ";\n";
+ f << indent << "value<" << wire->width << "> prev_" << mangle(wire) << ";\n";
}
for (auto edge_type : edge_types) {
if (edge_type.first.wire == wire) {
@@ -1642,49 +1849,67 @@ struct CxxrtlWorker {
f << "value<" << wire->width << "> " << mangle(wire) << ";\n";
}
- void dump_memory(RTLIL::Module *module, const RTLIL::Memory *memory)
+ void dump_reset_method(RTLIL::Module *module)
{
- vector<const RTLIL::Cell*> init_cells;
- for (auto cell : module->cells())
- if (cell->type == ID($meminit) && cell->getParam(ID::MEMID).decode_string() == memory->name.str())
- init_cells.push_back(cell);
+ int mem_init_idx = 0;
+ inc_indent();
+ for (auto wire : module->wires()) {
+ const auto &wire_type = wire_types[wire];
+ if (!wire_type.is_named() || wire_type.is_local()) continue;
+ if (!wire_init.count(wire)) continue;
- std::sort(init_cells.begin(), init_cells.end(), [](const RTLIL::Cell *a, const RTLIL::Cell *b) {
- int a_addr = a->getPort(ID::ADDR).as_int(), b_addr = b->getPort(ID::ADDR).as_int();
- int a_prio = a->getParam(ID::PRIORITY).as_int(), b_prio = b->getParam(ID::PRIORITY).as_int();
- return a_prio > b_prio || (a_prio == b_prio && a_addr < b_addr);
- });
+ f << indent << mangle(wire) << " = ";
+ if (wire_types[wire].is_buffered()) {
+ f << "wire<" << wire->width << ">";
+ } else {
+ f << "value<" << wire->width << ">";
+ }
+ dump_const_init(wire_init.at(wire), wire->width);
+ f << ";\n";
- dump_attrs(memory);
- f << indent << "memory<" << memory->width << "> " << mangle(memory)
- << " { " << memory->size << "u";
- if (init_cells.empty()) {
- f << " };\n";
- } else {
- f << ",\n";
- inc_indent();
- for (auto cell : init_cells) {
- dump_attrs(cell);
- RTLIL::Const data = cell->getPort(ID::DATA).as_const();
- size_t width = cell->getParam(ID::WIDTH).as_int();
- size_t words = cell->getParam(ID::WORDS).as_int();
- f << indent << "memory<" << memory->width << ">::init<" << words << "> { "
- << stringf("%#x", cell->getPort(ID::ADDR).as_int()) << ", {";
+ if (edge_wires[wire] && !wire_types[wire].is_buffered()) {
+ f << indent << "prev_" << mangle(wire) << " = ";
+ dump_const(wire_init.at(wire), wire->width);
+ f << ";\n";
+ }
+ }
+ for (auto &mem : mod_memories[module]) {
+ for (auto &init : mem.inits) {
+ if (init.removed)
+ continue;
+ dump_attrs(&init);
+ int words = GetSize(init.data) / mem.width;
+ f << indent << "static const value<" << mem.width << "> ";
+ f << "mem_init_" << ++mem_init_idx << "[" << words << "] {";
inc_indent();
- for (size_t n = 0; n < words; n++) {
+ for (int n = 0; n < words; n++) {
if (n % 4 == 0)
f << "\n" << indent;
else
f << " ";
- dump_const(data, width, n * width, /*fixed_width=*/true);
+ dump_const(init.data, mem.width, n * mem.width, /*fixed_width=*/true);
f << ",";
}
dec_indent();
- f << "\n" << indent << "}},\n";
+ f << "\n";
+ f << indent << "};\n";
+ f << indent << "std::copy(std::begin(mem_init_" << mem_init_idx << "), ";
+ f << "std::end(mem_init_" << mem_init_idx << "), ";
+ f << "&" << mangle(&mem) << ".data[" << stringf("%#x", init.addr.as_int()) << "]);\n";
}
- dec_indent();
- f << indent << "};\n";
- }
+ }
+ for (auto cell : module->cells()) {
+ if (is_internal_cell(cell->type))
+ continue;
+ f << indent << mangle(cell);
+ RTLIL::Module *cell_module = module->design->module(cell->type);
+ if (cell_module->get_bool_attribute(ID(cxxrtl_blackbox))) {
+ f << "->reset();\n";
+ } else {
+ f << ".reset();\n";
+ }
+ }
+ dec_indent();
}
void dump_eval_method(RTLIL::Module *module)
@@ -1721,11 +1946,17 @@ struct CxxrtlWorker {
case FlowGraph::Node::Type::CELL_EVAL:
dump_cell_eval(node.cell);
break;
+ case FlowGraph::Node::Type::PROCESS_CASE:
+ dump_process_case(node.process);
+ break;
case FlowGraph::Node::Type::PROCESS_SYNC:
dump_process_syncs(node.process);
break;
- case FlowGraph::Node::Type::PROCESS_CASE:
- dump_process_case(node.process);
+ case FlowGraph::Node::Type::MEM_RDPORT:
+ dump_mem_rdport(node.mem, node.portidx);
+ break;
+ case FlowGraph::Node::Type::MEM_WRPORTS:
+ dump_mem_wrports(node.mem);
break;
}
}
@@ -1750,6 +1981,18 @@ struct CxxrtlWorker {
case FlowGraph::Node::Type::CELL_EVAL:
dump_cell_eval(node.cell, /*for_debug=*/true);
break;
+ case FlowGraph::Node::Type::PROCESS_CASE:
+ dump_process_case(node.process, /*for_debug=*/true);
+ break;
+ case FlowGraph::Node::Type::PROCESS_SYNC:
+ dump_process_syncs(node.process, /*for_debug=*/true);
+ break;
+ case FlowGraph::Node::Type::MEM_RDPORT:
+ dump_mem_rdport(node.mem, node.portidx, /*for_debug=*/true);
+ break;
+ case FlowGraph::Node::Type::MEM_WRPORTS:
+ dump_mem_wrports(node.mem, /*for_debug=*/true);
+ break;
default:
log_abort();
}
@@ -1769,10 +2012,10 @@ struct CxxrtlWorker {
f << indent << "if (" << mangle(wire) << ".commit()) changed = true;\n";
}
if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) {
- for (auto memory : module->memories) {
- if (!writable_memories[memory.second])
+ for (auto &mem : mod_memories[module]) {
+ if (!writable_memories.count({module, mem.memid}))
continue;
- f << indent << "if (" << mangle(memory.second) << ".commit()) changed = true;\n";
+ f << indent << "if (" << mangle(&mem) << ".commit()) changed = true;\n";
}
for (auto cell : module->cells()) {
if (is_internal_cell(cell->type))
@@ -1914,12 +2157,12 @@ struct CxxrtlWorker {
}
}
if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) {
- for (auto &memory_it : module->memories) {
- if (!memory_it.first.isPublic())
+ for (auto &mem : mod_memories[module]) {
+ if (!mem.memid.isPublic())
continue;
- f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(memory_it.second));
- f << ", debug_item(" << mangle(memory_it.second) << ", ";
- f << memory_it.second->start_offset << "));\n";
+ f << indent << "items.add(path + " << escape_cxx_string(mem.packed ? get_hdl_name(mem.cell) : get_hdl_name(mem.mem));
+ f << ", debug_item(" << mangle(&mem) << ", ";
+ f << mem.start_offset << "));\n";
}
for (auto cell : module->cells()) {
if (is_internal_cell(cell->type))
@@ -1987,6 +2230,10 @@ struct CxxrtlWorker {
dump_wire(wire, /*is_local=*/false);
}
f << "\n";
+ f << indent << "void reset() override {\n";
+ dump_reset_method(module);
+ f << indent << "}\n";
+ f << "\n";
f << indent << "bool eval() override {\n";
dump_eval_method(module);
f << indent << "}\n";
@@ -2034,8 +2281,10 @@ struct CxxrtlWorker {
for (auto wire : module->wires())
dump_debug_wire(wire, /*is_local=*/false);
bool has_memories = false;
- for (auto memory : module->memories) {
- dump_memory(module, memory.second);
+ for (auto &mem : mod_memories[module]) {
+ dump_attrs(&mem);
+ f << indent << "memory<" << mem.width << "> " << mangle(&mem)
+ << " { " << mem.size << "u };\n";
has_memories = true;
}
if (has_memories)
@@ -2056,52 +2305,20 @@ struct CxxrtlWorker {
dump_metadata_map(cell->attributes);
f << ");\n";
} else {
- f << indent << mangle(cell_module) << " " << mangle(cell) << ";\n";
+ f << indent << mangle(cell_module) << " " << mangle(cell) << " {interior()};\n";
}
has_cells = true;
}
if (has_cells)
f << "\n";
- f << indent << mangle(module) << "() {}\n";
- if (has_cells) {
- f << indent << mangle(module) << "(adopt, " << mangle(module) << " other) :\n";
- bool first = true;
- for (auto cell : module->cells()) {
- if (is_internal_cell(cell->type))
- continue;
- if (first) {
- first = false;
- } else {
- f << ",\n";
- }
- RTLIL::Module *cell_module = module->design->module(cell->type);
- if (cell_module->get_bool_attribute(ID(cxxrtl_blackbox))) {
- f << indent << " " << mangle(cell) << "(std::move(other." << mangle(cell) << "))";
- } else {
- f << indent << " " << mangle(cell) << "(adopt {}, std::move(other." << mangle(cell) << "))";
- }
- }
- f << " {\n";
- inc_indent();
- for (auto cell : module->cells()) {
- if (is_internal_cell(cell->type))
- continue;
- RTLIL::Module *cell_module = module->design->module(cell->type);
- if (cell_module->get_bool_attribute(ID(cxxrtl_blackbox)))
- f << indent << mangle(cell) << "->reset();\n";
- }
- dec_indent();
- f << indent << "}\n";
- } else {
- f << indent << mangle(module) << "(adopt, " << mangle(module) << " other) {}\n";
- }
- f << "\n";
- f << indent << "void reset() override {\n";
+ f << indent << mangle(module) << "(interior) {}\n";
+ f << indent << mangle(module) << "() {\n";
inc_indent();
- f << indent << "*this = " << mangle(module) << "(adopt {}, std::move(*this));\n";
+ f << indent << "reset();\n";
dec_indent();
- f << indent << "}\n";
+ f << indent << "};\n";
f << "\n";
+ f << indent << "void reset() override;\n";
f << indent << "bool eval() override;\n";
f << indent << "bool commit() override;\n";
if (debug_info) {
@@ -2128,6 +2345,10 @@ struct CxxrtlWorker {
{
if (module->get_bool_attribute(ID(cxxrtl_blackbox)))
return;
+ f << indent << "void " << mangle(module) << "::reset() {\n";
+ dump_reset_method(module);
+ f << indent << "}\n";
+ f << "\n";
f << indent << "bool " << mangle(module) << "::eval() {\n";
dump_eval_method(module);
f << indent << "}\n";
@@ -2273,6 +2494,8 @@ struct CxxrtlWorker {
void register_edge_signal(SigMap &sigmap, RTLIL::SigSpec signal, RTLIL::SyncType type)
{
signal = sigmap(signal);
+ if (signal.is_fully_const())
+ return; // a clock, or more commonly a reset, can be tied to a constant driver
log_assert(is_valid_clock(signal));
log_assert(type == RTLIL::STp || type == RTLIL::STn || type == RTLIL::STe);
@@ -2297,6 +2520,13 @@ struct CxxrtlWorker {
SigMap &sigmap = sigmaps[module];
sigmap.set(module);
+ std::vector<Mem> &memories = mod_memories[module];
+ memories = Mem::get_all_memories(module);
+ for (auto &mem : memories) {
+ mem.narrow();
+ mem.coalesce_inits();
+ }
+
if (module->get_bool_attribute(ID(cxxrtl_blackbox))) {
for (auto port : module->ports) {
RTLIL::Wire *wire = module->wire(port);
@@ -2334,6 +2564,10 @@ struct CxxrtlWorker {
continue;
}
+ for (auto wire : module->wires())
+ if (wire->has_attribute(ID::init))
+ wire_init[wire] = wire->attributes.at(ID::init);
+
// Construct a flow graph where each node is a basic computational operation generally corresponding
// to a fragment of the RTLIL netlist.
FlowGraph flow;
@@ -2341,13 +2575,13 @@ struct CxxrtlWorker {
for (auto conn : module->connections())
flow.add_node(conn);
- dict<const RTLIL::Cell*, FlowGraph::Node*> memrw_cell_nodes;
- dict<std::pair<RTLIL::SigBit, const RTLIL::Memory*>,
- pool<const RTLIL::Cell*>> memwr_per_domain;
for (auto cell : module->cells()) {
if (!cell->known())
log_cmd_error("Unknown cell `%s'.\n", log_id(cell->type));
+ if (cell->is_mem_cell())
+ continue;
+
RTLIL::Module *cell_module = design->module(cell->type);
if (cell_module &&
cell_module->get_blackbox_attribute() &&
@@ -2359,58 +2593,54 @@ struct CxxrtlWorker {
cell_module->get_bool_attribute(ID(cxxrtl_template)))
blackbox_specializations[cell_module].insert(template_args(cell));
- FlowGraph::Node *node = flow.add_node(cell);
+ flow.add_node(cell);
// Various DFF cells are treated like posedge/negedge processes, see above for details.
- if (cell->type.in(ID($dff), ID($dffe), ID($adff), ID($adffe), ID($dffsr), ID($dffsre), ID($sdff), ID($sdffe), ID($sdffce))) {
+ if (cell->type.in(ID($dff), ID($dffe), ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre), ID($sdff), ID($sdffe), ID($sdffce))) {
if (is_valid_clock(cell->getPort(ID::CLK)))
register_edge_signal(sigmap, cell->getPort(ID::CLK),
cell->parameters[ID::CLK_POLARITY].as_bool() ? RTLIL::STp : RTLIL::STn);
}
- // Similar for memory port cells.
- if (cell->type.in(ID($memrd), ID($memwr))) {
- if (cell->getParam(ID::CLK_ENABLE).as_bool()) {
- if (is_valid_clock(cell->getPort(ID::CLK)))
- register_edge_signal(sigmap, cell->getPort(ID::CLK),
- cell->parameters[ID::CLK_POLARITY].as_bool() ? RTLIL::STp : RTLIL::STn);
- }
- memrw_cell_nodes[cell] = node;
- }
- // Optimize access to read-only memories.
- if (cell->type == ID($memwr))
- writable_memories.insert(module->memories[cell->getParam(ID::MEMID).decode_string()]);
- // Collect groups of memory write ports in the same domain.
- if (cell->type == ID($memwr) && cell->getParam(ID::CLK_ENABLE).as_bool() && is_valid_clock(cell->getPort(ID::CLK))) {
- RTLIL::SigBit clk_bit = sigmap(cell->getPort(ID::CLK))[0];
- const RTLIL::Memory *memory = module->memories[cell->getParam(ID::MEMID).decode_string()];
- memwr_per_domain[{clk_bit, memory}].insert(cell);
- }
- // Handling of packed memories is delegated to the `memory_unpack` pass, so we can rely on the presence
- // of RTLIL memory objects and $memrd/$memwr/$meminit cells.
- if (cell->type.in(ID($mem)))
- log_assert(false);
}
- for (auto cell : module->cells()) {
- // Collect groups of memory write ports read by every transparent read port.
- if (cell->type == ID($memrd) && cell->getParam(ID::CLK_ENABLE).as_bool() && is_valid_clock(cell->getPort(ID::CLK)) &&
- cell->getParam(ID::TRANSPARENT).as_bool()) {
- RTLIL::SigBit clk_bit = sigmap(cell->getPort(ID::CLK))[0];
- const RTLIL::Memory *memory = module->memories[cell->getParam(ID::MEMID).decode_string()];
- for (auto memwr_cell : memwr_per_domain[{clk_bit, memory}]) {
- transparent_for[cell].insert(memwr_cell);
- // Our implementation of transparent $memrd cells reads \EN, \ADDR and \DATA from every $memwr cell
- // in the same domain, which isn't directly visible in the netlist. Add these uses explicitly.
- flow.add_uses(memrw_cell_nodes[cell], memwr_cell->getPort(ID::EN));
- flow.add_uses(memrw_cell_nodes[cell], memwr_cell->getPort(ID::ADDR));
- flow.add_uses(memrw_cell_nodes[cell], memwr_cell->getPort(ID::DATA));
+
+ for (auto &mem : memories) {
+ flow.add_node(&mem);
+
+ // Clocked memory cells are treated like posedge/negedge processes as well.
+ for (auto &port : mem.rd_ports) {
+ if (port.clk_enable)
+ if (is_valid_clock(port.clk))
+ register_edge_signal(sigmap, port.clk,
+ port.clk_polarity ? RTLIL::STp : RTLIL::STn);
+ // For read ports, also move initial value to wire_init (if any).
+ for (int i = 0; i < GetSize(port.data); i++) {
+ if (port.init_value[i] != State::Sx) {
+ SigBit bit = port.data[i];
+ if (bit.wire) {
+ auto &init = wire_init[bit.wire];
+ if (init == RTLIL::Const()) {
+ init = RTLIL::Const(State::Sx, GetSize(bit.wire));
+ }
+ init[bit.offset] = port.init_value[i];
+ }
+ }
}
}
+ for (auto &port : mem.wr_ports) {
+ if (port.clk_enable)
+ if (is_valid_clock(port.clk))
+ register_edge_signal(sigmap, port.clk,
+ port.clk_polarity ? RTLIL::STp : RTLIL::STn);
+ }
+
+ if (!mem.wr_ports.empty())
+ writable_memories.insert({module, mem.memid});
}
for (auto proc : module->processes) {
flow.add_node(proc.second);
- for (auto sync : proc.second->syncs)
+ for (auto sync : proc.second->syncs) {
switch (sync->type) {
// Edge-type sync rules require pre-registration.
case RTLIL::STp:
@@ -2433,6 +2663,10 @@ struct CxxrtlWorker {
case RTLIL::STi:
log_assert(false);
}
+ for (auto &memwr : sync->mem_write_actions) {
+ writable_memories.insert({module, memwr.memid});
+ }
+ }
}
// Construct a linear order of the flow graph that minimizes the amount of feedback arcs. A flow graph
@@ -2502,6 +2736,10 @@ struct CxxrtlWorker {
for (auto node : flow.nodes) {
if (node->type == FlowGraph::Node::Type::CELL_EVAL && is_effectful_cell(node->cell->type))
worklist.insert(node); // node has effects
+ else if (node->type == FlowGraph::Node::Type::MEM_WRPORTS)
+ worklist.insert(node); // node is memory write
+ else if (node->type == FlowGraph::Node::Type::PROCESS_SYNC && is_memwr_process(node->process))
+ worklist.insert(node); // node is memory write
else if (flow.node_sync_defs.count(node))
worklist.insert(node); // node is a flip-flop
else if (flow.node_comb_defs.count(node)) {
@@ -2527,12 +2765,14 @@ struct CxxrtlWorker {
for (auto wire : module->wires()) {
auto &wire_type = wire_types[wire];
if (!wire_type.is_local()) continue;
- if (!wire->name.isPublic() && !inline_internal) continue;
- if (wire->name.isPublic() && !inline_public) continue;
-
if (live_wires[wire].empty()) {
wire_type = {WireType::UNUSED}; // wire never used
- } else if (flow.is_inlinable(wire, live_wires[wire])) {
+ continue;
+ }
+
+ if (!wire->name.isPublic() && !inline_internal) continue;
+ if (wire->name.isPublic() && !inline_public) continue;
+ if (flow.is_inlinable(wire, live_wires[wire])) {
if (flow.wire_comb_defs[wire].size() > 1)
log_cmd_error("Wire %s.%s has multiple drivers!\n", log_id(module), log_id(wire));
log_assert(flow.wire_comb_defs[wire].size() == 1);
@@ -2586,12 +2826,12 @@ struct CxxrtlWorker {
for (auto wire : module->wires()) {
const auto &wire_type = wire_types[wire];
auto &debug_wire_type = debug_wire_types[wire];
- if (wire_type.type == WireType::UNUSED) continue;
- if (!wire->name.isPublic()) continue;
if (!debug_info) continue;
if (wire->port_input || wire_type.is_buffered())
debug_wire_type = wire_type; // wire contains state
+ else if (!wire->name.isPublic())
+ continue; // internal and stateless
if (!debug_member) continue;
if (wire_type.is_member())
@@ -2655,7 +2895,7 @@ struct CxxrtlWorker {
auto &debug_wire_type = debug_wire_types[wire];
if (wire->name.isPublic()) continue;
- if (live_wires[wire].empty() || debug_live_wires[wire].empty()) {
+ if (debug_live_wires[wire].empty()) {
continue; // wire never used
} else if (flow.is_inlinable(wire, debug_live_wires[wire])) {
log_assert(flow.wire_comb_defs[wire].size() == 1);
@@ -2666,16 +2906,25 @@ struct CxxrtlWorker {
debug_wire_type = {WireType::INLINE, node->cell}; // wire replaced with cell
break;
case FlowGraph::Node::Type::CONNECT:
- debug_wire_type = {WireType::INLINE, node->connect.second}; // wire replaced with sig
+ debug_wire_type = {WireType::INLINE, node->connect.second}; // wire replaced with sig
break;
default: continue;
}
debug_live_nodes.erase(node);
- } else if (wire_type.is_local()) {
- debug_wire_type = {WireType::LOCAL}; // wire not inlinable
+ } else if (wire_type.is_member() || wire_type.type == WireType::LOCAL) {
+ debug_wire_type = wire_type; // wire not inlinable
} else {
- log_assert(wire_type.is_member());
- debug_wire_type = wire_type; // wire is a member
+ log_assert(wire_type.type == WireType::INLINE ||
+ wire_type.type == WireType::UNUSED);
+ if (flow.wire_comb_defs[wire].size() == 0) {
+ if (wire_init.count(wire)) { // wire never modified
+ debug_wire_type = {WireType::CONST, wire_init.at(wire)};
+ } else {
+ debug_wire_type = {WireType::CONST, RTLIL::SigSpec(RTLIL::S0, wire->width)};
+ }
+ } else {
+ debug_wire_type = {WireType::LOCAL}; // wire used only for debug
+ }
}
}
@@ -2684,6 +2933,35 @@ struct CxxrtlWorker {
if (debug_live_nodes[node])
debug_schedule[module].push_back(*node);
}
+
+ auto show_wire_type = [&](const RTLIL::Wire* wire, const WireType &wire_type) {
+ const char *type_str;
+ switch (wire_type.type) {
+ case WireType::UNUSED: type_str = "UNUSED"; break;
+ case WireType::BUFFERED: type_str = "BUFFERED"; break;
+ case WireType::MEMBER: type_str = "MEMBER"; break;
+ case WireType::OUTLINE: type_str = "OUTLINE"; break;
+ case WireType::LOCAL: type_str = "LOCAL"; break;
+ case WireType::INLINE: type_str = "INLINE"; break;
+ case WireType::ALIAS: type_str = "ALIAS"; break;
+ case WireType::CONST: type_str = "CONST"; break;
+ default: type_str = "(invalid)";
+ }
+ if (wire_type.sig_subst.empty())
+ log_debug(" %s: %s\n", log_signal((RTLIL::Wire*)wire), type_str);
+ else
+ log_debug(" %s: %s = %s\n", log_signal((RTLIL::Wire*)wire), type_str, log_signal(wire_type.sig_subst));
+ };
+ if (print_wire_types && !wire_types.empty()) {
+ log_debug("Wire types:\n");
+ for (auto wire_type : wire_types)
+ show_wire_type(wire_type.first, wire_type.second);
+ }
+ if (print_debug_wire_types && !debug_wire_types.empty()) {
+ log_debug("Debug wire types:\n");
+ for (auto debug_wire_type : debug_wire_types)
+ show_wire_type(debug_wire_type.first, debug_wire_type.second);
+ }
}
if (has_feedback_arcs || has_buffered_comb_wires) {
// Although both non-feedback buffered combinatorial wires and apparent feedback wires may be eliminated
@@ -2702,9 +2980,9 @@ struct CxxrtlWorker {
}
}
- void check_design(RTLIL::Design *design, bool &has_top, bool &has_sync_init, bool &has_packed_mem)
+ void check_design(RTLIL::Design *design, bool &has_sync_init)
{
- has_sync_init = has_packed_mem = has_top = false;
+ has_sync_init = false;
for (auto module : design->modules()) {
if (module->get_blackbox_attribute() && !module->has_attribute(ID(cxxrtl_blackbox)))
@@ -2716,28 +2994,20 @@ struct CxxrtlWorker {
if (!design->selected_module(module))
continue;
- if (module->get_bool_attribute(ID::top))
- has_top = true;
-
for (auto proc : module->processes)
for (auto sync : proc.second->syncs)
if (sync->type == RTLIL::STi)
has_sync_init = true;
-
- // The Mem constructor also checks for well-formedness of $meminit cells, if any.
- for (auto &mem : Mem::get_all_memories(module))
- if (mem.packed)
- has_packed_mem = true;
}
}
void prepare_design(RTLIL::Design *design)
{
bool did_anything = false;
- bool has_top, has_sync_init, has_packed_mem;
+ bool has_sync_init;
log_push();
- check_design(design, has_top, has_sync_init, has_packed_mem);
- if (run_hierarchy && !has_top) {
+ check_design(design, has_sync_init);
+ if (run_hierarchy) {
Pass::call(design, "hierarchy -auto-top");
did_anything = true;
}
@@ -2756,14 +3026,10 @@ struct CxxrtlWorker {
Pass::call(design, "proc_init");
did_anything = true;
}
- if (has_packed_mem) {
- Pass::call(design, "memory_unpack");
- did_anything = true;
- }
// Recheck the design if it was modified.
if (did_anything)
- check_design(design, has_top, has_sync_init, has_packed_mem);
- log_assert(has_top && !has_sync_init && !has_packed_mem);
+ check_design(design, has_sync_init);
+ log_assert(!has_sync_init);
log_pop();
if (did_anything)
log_spacer();
@@ -2934,6 +3200,9 @@ struct CxxrtlBackend : public Backend {
log("\n");
log("The following options are supported by this backend:\n");
log("\n");
+ log(" -print-wire-types, -print-debug-wire-types\n");
+ log(" enable additional debug logging, for pass developers.\n");
+ log("\n");
log(" -header\n");
log(" generate separate interface (.h) and implementation (.cc) files.\n");
log(" if specified, the backend must be called with a filename, and filename\n");
@@ -3013,6 +3282,8 @@ struct CxxrtlBackend : public Backend {
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
{
+ bool print_wire_types = false;
+ bool print_debug_wire_types = false;
bool nohierarchy = false;
bool noflatten = false;
bool noproc = false;
@@ -3025,6 +3296,14 @@ struct CxxrtlBackend : public Backend {
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
+ if (args[argidx] == "-print-wire-types") {
+ print_wire_types = true;
+ continue;
+ }
+ if (args[argidx] == "-print-debug-wire-types") {
+ print_debug_wire_types = true;
+ continue;
+ }
if (args[argidx] == "-nohierarchy") {
nohierarchy = true;
continue;
@@ -3076,6 +3355,8 @@ struct CxxrtlBackend : public Backend {
}
extra_args(f, filename, args, argidx);
+ worker.print_wire_types = print_wire_types;
+ worker.print_debug_wire_types = print_debug_wire_types;
worker.run_hierarchy = !nohierarchy;
worker.run_flatten = !noflatten;
worker.run_proc = !noproc;
diff --git a/backends/cxxrtl/cxxrtl_vcd.h b/backends/cxxrtl/cxxrtl_vcd.h
index 3f40a8d12..b76922bbd 100644
--- a/backends/cxxrtl/cxxrtl_vcd.h
+++ b/backends/cxxrtl/cxxrtl_vcd.h
@@ -69,12 +69,25 @@ class vcd_writer {
} while (ident != 0);
}
+ void emit_name(const std::string &name) {
+ for (char c : name) {
+ if (c == ':') {
+ // Due to a bug, GTKWave cannot parse a colon in the variable name, causing the VCD file
+ // to be unreadable. It cannot be escaped either, so replace it with the sideways colon.
+ buffer += "..";
+ } else {
+ buffer += c;
+ }
+ }
+ }
+
void emit_var(const variable &var, const std::string &type, const std::string &name,
size_t lsb_at, bool multipart) {
assert(!streaming);
buffer += "$var " + type + " " + std::to_string(var.width) + " ";
emit_ident(var.ident);
- buffer += " " + name;
+ buffer += " ";
+ emit_name(name);
if (multipart || name.back() == ']' || lsb_at != 0) {
if (var.width == 1)
buffer += " [" + std::to_string(lsb_at) + "]";
diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc
index e0013238c..370108444 100644
--- a/backends/edif/edif.cc
+++ b/backends/edif/edif.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc
index 44c3397da..85c44824f 100644
--- a/backends/firrtl/firrtl.cc
+++ b/backends/firrtl/firrtl.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -23,6 +23,7 @@
#include "kernel/celltypes.h"
#include "kernel/cellaigs.h"
#include "kernel/log.h"
+#include "kernel/mem.h"
#include <algorithm>
#include <string>
#include <vector>
@@ -366,126 +367,6 @@ struct FirrtlWorker
RTLIL::Design *design;
std::string indent;
- // Define read/write ports and memories.
- // We'll collect their definitions and emit the corresponding FIRRTL definitions at the appropriate point in module construction.
- // For the moment, we don't handle $readmemh or $readmemb.
- // These will be part of a subsequent PR.
- struct read_port {
- string name;
- bool clk_enable;
- bool clk_parity;
- bool transparent;
- RTLIL::SigSpec clk;
- RTLIL::SigSpec ena;
- RTLIL::SigSpec addr;
- read_port(string name, bool clk_enable, bool clk_parity, bool transparent, RTLIL::SigSpec clk, RTLIL::SigSpec ena, RTLIL::SigSpec addr) : name(name), clk_enable(clk_enable), clk_parity(clk_parity), transparent(transparent), clk(clk), ena(ena), addr(addr) {
- // Current (3/13/2019) conventions:
- // generate a constant 0 for clock and a constant 1 for enable if they are undefined.
- if (!clk.is_fully_def())
- this->clk = SigSpec(State::S0);
- if (!ena.is_fully_def())
- this->ena = SigSpec(State::S1);
- }
- string gen_read(const char * indent) {
- string addr_expr = make_expr(addr);
- string ena_expr = make_expr(ena);
- string clk_expr = make_expr(clk);
- string addr_str = stringf("%s%s.addr <= %s\n", indent, name.c_str(), addr_expr.c_str());
- string ena_str = stringf("%s%s.en <= %s\n", indent, name.c_str(), ena_expr.c_str());
- string clk_str = stringf("%s%s.clk <= asClock(%s)\n", indent, name.c_str(), clk_expr.c_str());
- return addr_str + ena_str + clk_str;
- }
- };
- struct write_port : read_port {
- RTLIL::SigSpec mask;
- write_port(string name, bool clk_enable, bool clk_parity, bool transparent, RTLIL::SigSpec clk, RTLIL::SigSpec ena, RTLIL::SigSpec addr, RTLIL::SigSpec mask) : read_port(name, clk_enable, clk_parity, transparent, clk, ena, addr), mask(mask) {
- if (!clk.is_fully_def())
- this->clk = SigSpec(RTLIL::Const(0));
- if (!ena.is_fully_def())
- this->ena = SigSpec(RTLIL::Const(0));
- if (!mask.is_fully_def())
- this->ena = SigSpec(RTLIL::Const(1));
- }
- string gen_read(const char * /* indent */) {
- log_error("gen_read called on write_port: %s\n", name.c_str());
- return stringf("gen_read called on write_port: %s\n", name.c_str());
- }
- string gen_write(const char * indent) {
- string addr_expr = make_expr(addr);
- string ena_expr = make_expr(ena);
- string clk_expr = make_expr(clk);
- string mask_expr = make_expr(mask);
- string mask_str = stringf("%s%s.mask <= %s\n", indent, name.c_str(), mask_expr.c_str());
- string addr_str = stringf("%s%s.addr <= %s\n", indent, name.c_str(), addr_expr.c_str());
- string ena_str = stringf("%s%s.en <= %s\n", indent, name.c_str(), ena_expr.c_str());
- string clk_str = stringf("%s%s.clk <= asClock(%s)\n", indent, name.c_str(), clk_expr.c_str());
- return addr_str + ena_str + clk_str + mask_str;
- }
- };
- /* Memories defined within this module. */
- struct memory {
- Cell *pCell; // for error reporting
- string name; // memory name
- int abits; // number of address bits
- int size; // size (in units) of the memory
- int width; // size (in bits) of each element
- int read_latency;
- int write_latency;
- vector<read_port> read_ports;
- vector<write_port> write_ports;
- std::string init_file;
- std::string init_file_srcFileSpec;
- string srcLine;
- memory(Cell *pCell, string name, int abits, int size, int width) : pCell(pCell), name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") {
- // Provide defaults for abits or size if one (but not the other) is specified.
- if (this->abits == 0 && this->size != 0) {
- this->abits = ceil_log2(this->size);
- } else if (this->abits != 0 && this->size == 0) {
- this->size = 1 << this->abits;
- }
- // Sanity-check this construction.
- if (this->name == "") {
- log_error("Nameless memory%s\n", this->atLine());
- }
- if (this->abits == 0 && this->size == 0) {
- log_error("Memory %s has zero address bits and size%s\n", this->name.c_str(), this->atLine());
- }
- if (this->width == 0) {
- log_error("Memory %s has zero width%s\n", this->name.c_str(), this->atLine());
- }
- }
-
- // We need a default constructor for the dict insert.
- memory() : pCell(0), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){}
-
- const char *atLine() {
- if (srcLine == "") {
- if (pCell) {
- auto p = pCell->attributes.find(ID::src);
- srcLine = " at " + p->second.decode_string();
- }
- }
- return srcLine.c_str();
- }
- void add_memory_read_port(read_port &rp) {
- read_ports.push_back(rp);
- }
- void add_memory_write_port(write_port &wp) {
- write_ports.push_back(wp);
- }
- void add_memory_file(std::string init_file, std::string init_file_srcFileSpec) {
- this->init_file = init_file;
- this->init_file_srcFileSpec = init_file_srcFileSpec;
- }
-
- };
- dict<string, memory> memories;
-
- void register_memory(memory &m)
- {
- memories[m.name] = m;
- }
-
void register_reverse_wire_map(string id, SigSpec sig)
{
for (int i = 0; i < GetSize(sig); i++)
@@ -658,7 +539,11 @@ struct FirrtlWorker
{
std::string moduleFileinfo = getFileinfo(module);
f << stringf(" module %s: %s\n", make_id(module->name), moduleFileinfo.c_str());
- vector<string> port_decls, wire_decls, cell_exprs, wire_exprs;
+ vector<string> port_decls, wire_decls, mem_exprs, cell_exprs, wire_exprs;
+
+ std::vector<Mem> memories = Mem::get_all_memories(module);
+ for (auto &mem : memories)
+ mem.narrow();
for (auto wire : module->wires())
{
@@ -686,14 +571,15 @@ struct FirrtlWorker
for (auto cell : module->cells())
{
- static Const ndef(0, 0);
+ Const ndef(0, 0);
// Is this cell is a module instance?
- if (cell->type[0] != '$')
+ if (module->design->module(cell->type))
{
process_instance(cell, wire_exprs);
continue;
}
+
// Not a module instance. Set up cell properties
bool extract_y_bits = false; // Assume no extraction of final bits will be required.
int a_width = cell->parameters.at(ID::A_WIDTH, ndef).as_int(); // The width of "A"
@@ -1004,126 +890,9 @@ struct FirrtlWorker
continue;
}
- if (cell->type.in(ID($mem)))
- {
- string mem_id = make_id(cell->name);
- int abits = cell->parameters.at(ID::ABITS).as_int();
- int width = cell->parameters.at(ID::WIDTH).as_int();
- int size = cell->parameters.at(ID::SIZE).as_int();
- memory m(cell, mem_id, abits, size, width);
- int rd_ports = cell->parameters.at(ID::RD_PORTS).as_int();
- int wr_ports = cell->parameters.at(ID::WR_PORTS).as_int();
-
- Const initdata = cell->parameters.at(ID::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(ID::RD_CLK_ENABLE);
- Const wr_clk_enable = cell->parameters.at(ID::WR_CLK_ENABLE);
- Const wr_clk_polarity = cell->parameters.at(ID::WR_CLK_POLARITY);
-
- int offset = cell->parameters.at(ID::OFFSET).as_int();
- if (offset != 0)
- log_error("Memory with nonzero offset: %s.%s\n", log_id(module), log_id(cell));
-
- 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 addr_sig = cell->getPort(ID::RD_ADDR).extract(i*abits, abits);
- SigSpec data_sig = cell->getPort(ID::RD_DATA).extract(i*width, width);
- string addr_expr = make_expr(addr_sig);
- string name(stringf("%s.r%d", m.name.c_str(), i));
- bool clk_enable = false;
- bool clk_parity = true;
- bool transparency = false;
- SigSpec ena_sig = RTLIL::SigSpec(RTLIL::State::S1, 1);
- SigSpec clk_sig = RTLIL::SigSpec(RTLIL::State::S0, 1);
- read_port rp(name, clk_enable, clk_parity, transparency, clk_sig, ena_sig, addr_sig);
- m.add_memory_read_port(rp);
- cell_exprs.push_back(rp.gen_read(indent.c_str()));
- register_reverse_wire_map(stringf("%s.data", name.c_str()), 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 name(stringf("%s.w%d", m.name.c_str(), i));
- bool clk_enable = true;
- bool clk_parity = true;
- bool transparency = false;
- SigSpec addr_sig =cell->getPort(ID::WR_ADDR).extract(i*abits, abits);
- string addr_expr = make_expr(addr_sig);
- SigSpec data_sig =cell->getPort(ID::WR_DATA).extract(i*width, width);
- string data_expr = make_expr(data_sig);
- SigSpec clk_sig = cell->getPort(ID::WR_CLK).extract(i);
- string clk_expr = make_expr(clk_sig);
-
- SigSpec wen_sig = cell->getPort(ID::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));
-
- SigSpec mask_sig = RTLIL::SigSpec(RTLIL::State::S1, 1);
- write_port wp(name, clk_enable, clk_parity, transparency, clk_sig, wen_sig[0], addr_sig, mask_sig);
- m.add_memory_write_port(wp);
- cell_exprs.push_back(stringf("%s%s.data <= %s\n", indent.c_str(), name.c_str(), data_expr.c_str()));
- cell_exprs.push_back(wp.gen_write(indent.c_str()));
- }
- register_memory(m);
- continue;
- }
-
- if (cell->type.in(ID($memwr), ID($memrd), ID($meminit)))
+ if (cell->is_mem_cell())
{
- std::string cell_type = fid(cell->type);
- std::string mem_id = make_id(cell->parameters[ID::MEMID].decode_string());
- int abits = cell->parameters.at(ID::ABITS).as_int();
- int width = cell->parameters.at(ID::WIDTH).as_int();
- memory *mp = nullptr;
- if (cell->type == ID($meminit) ) {
- log_error("$meminit (%s.%s.%s) currently unsupported\n", log_id(module), log_id(cell), mem_id.c_str());
- } else {
- // It's a $memwr or $memrd. Remember the read/write port parameters for the eventual FIRRTL memory definition.
- auto addrSig = cell->getPort(ID::ADDR);
- auto dataSig = cell->getPort(ID::DATA);
- auto enableSig = cell->getPort(ID::EN);
- auto clockSig = cell->getPort(ID::CLK);
- Const clk_enable = cell->parameters.at(ID::CLK_ENABLE);
- Const clk_polarity = cell->parameters.at(ID::CLK_POLARITY);
-
- // Do we already have an entry for this memory?
- if (memories.count(mem_id) == 0) {
- memory m(cell, mem_id, abits, 0, width);
- register_memory(m);
- }
- mp = &memories.at(mem_id);
- int portNum = 0;
- bool transparency = false;
- string data_expr = make_expr(dataSig);
- if (cell->type.in(ID($memwr))) {
- portNum = (int) mp->write_ports.size();
- write_port wp(stringf("%s.w%d", mem_id.c_str(), portNum), clk_enable.as_bool(), clk_polarity.as_bool(), transparency, clockSig, enableSig, addrSig, dataSig);
- mp->add_memory_write_port(wp);
- cell_exprs.push_back(stringf("%s%s.data <= %s\n", indent.c_str(), wp.name.c_str(), data_expr.c_str()));
- cell_exprs.push_back(wp.gen_write(indent.c_str()));
- } else if (cell->type.in(ID($memrd))) {
- portNum = (int) mp->read_ports.size();
- read_port rp(stringf("%s.r%d", mem_id.c_str(), portNum), clk_enable.as_bool(), clk_polarity.as_bool(), transparency, clockSig, enableSig, addrSig);
- mp->add_memory_read_port(rp);
- cell_exprs.push_back(rp.gen_read(indent.c_str()));
- register_reverse_wire_map(stringf("%s.data", rp.name.c_str()), dataSig);
- }
- }
+ // Will be handled below, as part of a Mem.
continue;
}
@@ -1145,12 +914,6 @@ struct FirrtlWorker
continue;
}
- // This may be a parameterized module - paramod.
- if (cell->type.begins_with("$paramod"))
- {
- process_instance(cell, wire_exprs);
- continue;
- }
if (cell->type == ID($shiftx)) {
// assign y = a[b +: y_width];
// We'll extract the correct bits as part of the primop.
@@ -1215,6 +978,82 @@ struct FirrtlWorker
log_error("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell));
}
+ for (auto &mem : memories) {
+ string mem_id = make_id(mem.memid);
+
+ Const init_data = mem.get_init_data();
+ if (!init_data.is_fully_undef())
+ log_error("Memory with initialization data: %s.%s\n", log_id(module), log_id(mem.memid));
+
+ if (mem.start_offset != 0)
+ log_error("Memory with nonzero offset: %s.%s\n", log_id(module), log_id(mem.memid));
+
+ for (int i = 0; i < GetSize(mem.rd_ports); i++)
+ {
+ auto &port = mem.rd_ports[i];
+ string port_name(stringf("%s.r%d", mem_id.c_str(), i));
+
+ if (port.clk_enable)
+ log_error("Clocked read port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
+
+ std::ostringstream rpe;
+
+ string addr_expr = make_expr(port.addr);
+ string ena_expr = make_expr(State::S1);
+ string clk_expr = make_expr(State::S0);
+
+ rpe << stringf("%s%s.addr <= %s\n", indent.c_str(), port_name.c_str(), addr_expr.c_str());
+ rpe << stringf("%s%s.en <= %s\n", indent.c_str(), port_name.c_str(), ena_expr.c_str());
+ rpe << stringf("%s%s.clk <= asClock(%s)\n", indent.c_str(), port_name.c_str(), clk_expr.c_str());
+ cell_exprs.push_back(rpe.str());
+ register_reverse_wire_map(stringf("%s.data", port_name.c_str()), port.data);
+ }
+
+ for (int i = 0; i < GetSize(mem.wr_ports); i++)
+ {
+ auto &port = mem.wr_ports[i];
+ string port_name(stringf("%s.w%d", mem_id.c_str(), i));
+
+ if (!port.clk_enable)
+ log_error("Unclocked write port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
+ if (!port.clk_polarity)
+ log_error("Negedge write port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
+ for (int i = 1; i < GetSize(port.en); i++)
+ if (port.en[0] != port.en[i])
+ log_error("Complex write enable on port %d on memory %s.%s.\n", i, log_id(module), log_id(mem.memid));
+
+ std::ostringstream wpe;
+
+ string data_expr = make_expr(port.data);
+ string addr_expr = make_expr(port.addr);
+ string ena_expr = make_expr(port.en[0]);
+ string clk_expr = make_expr(port.clk);
+ string mask_expr = make_expr(State::S1);
+ wpe << stringf("%s%s.data <= %s\n", indent.c_str(), port_name.c_str(), data_expr.c_str());
+ wpe << stringf("%s%s.addr <= %s\n", indent.c_str(), port_name.c_str(), addr_expr.c_str());
+ wpe << stringf("%s%s.en <= %s\n", indent.c_str(), port_name.c_str(), ena_expr.c_str());
+ wpe << stringf("%s%s.clk <= asClock(%s)\n", indent.c_str(), port_name.c_str(), clk_expr.c_str());
+ wpe << stringf("%s%s.mask <= %s\n", indent.c_str(), port_name.c_str(), mask_expr.c_str());
+
+ cell_exprs.push_back(wpe.str());
+ }
+
+ std::ostringstream me;
+
+ me << stringf(" mem %s:\n", mem_id.c_str());
+ me << stringf(" data-type => UInt<%d>\n", mem.width);
+ me << stringf(" depth => %d\n", mem.size);
+ for (int i = 0; i < GetSize(mem.rd_ports); i++)
+ me << stringf(" reader => r%d\n", i);
+ for (int i = 0; i < GetSize(mem.wr_ports); i++)
+ me << stringf(" writer => w%d\n", i);
+ me << stringf(" read-latency => %d\n", 0);
+ me << stringf(" write-latency => %d\n", 1);
+ me << stringf(" read-under-write => undefined\n");
+
+ mem_exprs.push_back(me.str());
+ }
+
for (auto conn : module->connections())
{
string y_id = next_id();
@@ -1316,22 +1155,9 @@ struct FirrtlWorker
f << stringf("\n");
- // If we have any memory definitions, output them.
- for (auto kv : memories) {
- memory &m = kv.second;
- f << stringf(" mem %s:\n", m.name.c_str());
- f << stringf(" data-type => UInt<%d>\n", m.width);
- f << stringf(" depth => %d\n", m.size);
- for (int i = 0; i < (int) m.read_ports.size(); i += 1) {
- f << stringf(" reader => r%d\n", i);
- }
- for (int i = 0; i < (int) m.write_ports.size(); i += 1) {
- f << stringf(" writer => w%d\n", i);
- }
- f << stringf(" read-latency => %d\n", m.read_latency);
- f << stringf(" write-latency => %d\n", m.write_latency);
- f << stringf(" read-under-write => undefined\n");
- }
+ for (auto str : mem_exprs)
+ f << str;
+
f << stringf("\n");
for (auto str : cell_exprs)
@@ -1362,6 +1188,8 @@ struct FirrtlBackend : public Backend {
log("Write a FIRRTL netlist of the current design.\n");
log("The following commands are executed by this command:\n");
log(" pmuxtree\n");
+ log(" bmuxmap\n");
+ log(" demuxmap\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
@@ -1384,7 +1212,9 @@ struct FirrtlBackend : public Backend {
log_header(design, "Executing FIRRTL backend.\n");
log_push();
- Pass::call(design, stringf("pmuxtree"));
+ Pass::call(design, "pmuxtree");
+ Pass::call(design, "bmuxmap");
+ Pass::call(design, "demuxmap");
namecache.clear();
autoid_counter = 0;
diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc
index a6b36de6c..59173c4a2 100644
--- a/backends/intersynth/intersynth.cc
+++ b/backends/intersynth/intersynth.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -68,7 +68,7 @@ struct IntersynthBackend : public Backend {
log(" only write selected modules. modules must be selected entirely or\n");
log(" not at all.\n");
log("\n");
- log("http://www.clifford.at/intersynth/\n");
+ log("http://bygone.clairexen.net/intersynth/\n");
log("\n");
}
void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) override
diff --git a/backends/json/json.cc b/backends/json/json.cc
index eeadc1b89..4aa8046d6 100644
--- a/backends/json/json.cc
+++ b/backends/json/json.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -135,6 +135,10 @@ struct JsonWriter
// reserve 0 and 1 to avoid confusion with "0" and "1"
sigidcounter = 2;
+ if (module->has_processes()) {
+ log_error("Module %s contains processes, which are not supported by JSON backend (run `proc` first).\n", log_id(module));
+ }
+
f << stringf(" %s: {\n", get_name(module->name).c_str());
f << stringf(" \"attributes\": {");
@@ -216,6 +220,27 @@ struct JsonWriter
}
f << stringf("\n },\n");
+ if (!module->memories.empty()) {
+ f << stringf(" \"memories\": {");
+ first = true;
+ for (auto &it : module->memories) {
+ if (use_selection && !module->selected(it.second))
+ continue;
+ f << stringf("%s\n", first ? "" : ",");
+ f << stringf(" %s: {\n", get_name(it.second->name).c_str());
+ f << stringf(" \"hide_name\": %s,\n", it.second->name[0] == '$' ? "1" : "0");
+ f << stringf(" \"attributes\": {");
+ write_parameters(it.second->attributes);
+ f << stringf("\n },\n");
+ f << stringf(" \"width\": %d,\n", it.second->width);
+ f << stringf(" \"start_offset\": %d,\n", it.second->start_offset);
+ f << stringf(" \"size\": %d\n", it.second->size);
+ f << stringf(" }");
+ first = false;
+ }
+ f << stringf("\n },\n");
+ }
+
f << stringf(" \"netnames\": {");
first = true;
for (auto w : module->wires()) {
@@ -332,6 +357,10 @@ struct JsonBackend : public Backend {
log(" <cell_name>: <cell_details>,\n");
log(" ...\n");
log(" },\n");
+ log(" \"memories\": {\n");
+ log(" <memory_name>: <memory_details>,\n");
+ log(" ...\n");
+ log(" },\n");
log(" \"netnames\": {\n");
log(" <net_name>: <net_details>,\n");
log(" ...\n");
@@ -379,6 +408,19 @@ struct JsonBackend : public Backend {
log(" },\n");
log(" }\n");
log("\n");
+ log("And <memory_details> is:\n");
+ log("\n");
+ log(" {\n");
+ log(" \"hide_name\": <1 | 0>,\n");
+ log(" \"attributes\": {\n");
+ log(" <attribute_name>: <attribute_value>,\n");
+ log(" ...\n");
+ log(" },\n");
+ log(" \"width\": <memory width>\n");
+ log(" \"start_offset\": <the lowest valid memory address>\n");
+ log(" \"size\": <memory size>\n");
+ log(" }\n");
+ log("\n");
log("And <net_details> is:\n");
log("\n");
log(" {\n");
diff --git a/backends/protobuf/Makefile.inc b/backends/protobuf/Makefile.inc
index 834cad42c..9cac9dcaa 100644
--- a/backends/protobuf/Makefile.inc
+++ b/backends/protobuf/Makefile.inc
@@ -3,6 +3,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
+backends/protobuf/protobuf.cc: backends/protobuf/yosys.pb.h
+
OBJS += backends/protobuf/protobuf.o backends/protobuf/yosys.pb.o
endif
diff --git a/backends/protobuf/protobuf.cc b/backends/protobuf/protobuf.cc
index f6623a382..384ce2e8e 100644
--- a/backends/protobuf/protobuf.cc
+++ b/backends/protobuf/protobuf.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/backends/rtlil/rtlil_backend.cc b/backends/rtlil/rtlil_backend.cc
index 01b4bde53..1b11de5ec 100644
--- a/backends/rtlil/rtlil_backend.cc
+++ b/backends/rtlil/rtlil_backend.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -51,15 +51,19 @@ void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi
}
}
f << stringf("%d'", width);
- for (int i = offset+width-1; i >= offset; i--) {
- log_assert(i < (int)data.bits.size());
- switch (data.bits[i]) {
- case State::S0: f << stringf("0"); break;
- case State::S1: f << stringf("1"); break;
- case RTLIL::Sx: f << stringf("x"); break;
- case RTLIL::Sz: f << stringf("z"); break;
- case RTLIL::Sa: f << stringf("-"); break;
- case RTLIL::Sm: f << stringf("m"); break;
+ if (data.is_fully_undef()) {
+ f << "x";
+ } else {
+ for (int i = offset+width-1; i >= offset; i--) {
+ log_assert(i < (int)data.bits.size());
+ switch (data.bits[i]) {
+ case State::S0: f << stringf("0"); break;
+ case State::S1: f << stringf("1"); break;
+ case RTLIL::Sx: f << stringf("x"); break;
+ case RTLIL::Sz: f << stringf("z"); break;
+ case RTLIL::Sa: f << stringf("-"); break;
+ case RTLIL::Sm: f << stringf("m"); break;
+ }
}
}
} else {
@@ -242,11 +246,28 @@ void RTLIL_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT
case RTLIL::STi: f << stringf("init\n"); break;
}
- for (auto it = sy->actions.begin(); it != sy->actions.end(); ++it) {
+ for (auto &it: sy->actions) {
f << stringf("%s update ", indent.c_str());
- dump_sigspec(f, it->first);
+ dump_sigspec(f, it.first);
f << stringf(" ");
- dump_sigspec(f, it->second);
+ dump_sigspec(f, it.second);
+ f << stringf("\n");
+ }
+
+ for (auto &it: sy->mem_write_actions) {
+ for (auto it2 = it.attributes.begin(); it2 != it.attributes.end(); ++it2) {
+ f << stringf("%s attribute %s ", indent.c_str(), it2->first.c_str());
+ dump_const(f, it2->second);
+ f << stringf("\n");
+ }
+ f << stringf("%s memwr %s ", indent.c_str(), it.memid.c_str());
+ dump_sigspec(f, it.address);
+ f << stringf(" ");
+ dump_sigspec(f, it.data);
+ f << stringf(" ");
+ dump_sigspec(f, it.enable);
+ f << stringf(" ");
+ dump_const(f, it.priority_mask);
f << stringf("\n");
}
}
@@ -337,8 +358,8 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
bool first_conn_line = true;
for (auto it = module->connections().begin(); it != module->connections().end(); ++it) {
- bool show_conn = !only_selected;
- if (only_selected) {
+ bool show_conn = !only_selected || design->selected_whole_module(module->name);
+ if (!show_conn) {
RTLIL::SigSpec sigs = it->first;
sigs.append(it->second);
for (auto &c : sigs.chunks()) {
diff --git a/backends/rtlil/rtlil_backend.h b/backends/rtlil/rtlil_backend.h
index 77eea353c..35829729c 100644
--- a/backends/rtlil/rtlil_backend.h
+++ b/backends/rtlil/rtlil_backend.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/backends/simplec/simplec.cc b/backends/simplec/simplec.cc
index 3adeaa6c0..e283dcf7c 100644
--- a/backends/simplec/simplec.cc
+++ b/backends/simplec/simplec.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc
index 8be9e05f1..a928419a1 100644
--- a/backends/smt2/smt2.cc
+++ b/backends/smt2/smt2.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -124,6 +124,7 @@ struct Smt2Worker
memories = Mem::get_all_memories(module);
for (auto &mem : memories)
{
+ mem.narrow();
mem_dict[mem.memid] = &mem;
for (auto &port : mem.wr_ports)
{
@@ -182,7 +183,7 @@ struct Smt2Worker
continue;
// Handled above.
- if (cell->type.in(ID($mem), ID($memrd), ID($memwr), ID($meminit))) {
+ if (cell->is_mem_cell()) {
mem_cells[cell] = mem_dict[cell->parameters.at(ID::MEMID).decode_string()];
continue;
}
@@ -694,7 +695,7 @@ struct Smt2Worker
// FIXME: $slice $concat
}
- if (memmode && cell->type.in(ID($mem), ID($memrd), ID($memwr), ID($meminit)))
+ if (memmode && cell->is_mem_cell())
{
Mem *mem = mem_cells[cell];
@@ -859,7 +860,7 @@ struct Smt2Worker
log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smt2`.\n",
log_id(cell->type), log_id(module), log_id(cell));
}
- if (cell->type.in(ID($adff), ID($adffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF") {
+ if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") {
log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_smt2`.\n",
log_id(cell->type), log_id(module), log_id(cell));
}
@@ -1530,6 +1531,11 @@ struct Smt2Backend : public Backend {
log_header(design, "Executing SMT2 backend.\n");
+ log_push();
+ Pass::call(design, "bmuxmap");
+ Pass::call(design, "demuxmap");
+ log_pop();
+
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py
index da5a7f57e..e5cfcdc08 100644
--- a/backends/smt2/smtbmc.py
+++ b/backends/smt2/smtbmc.py
@@ -2,7 +2,7 @@
#
# yosys -- Yosys Open SYnthesis Suite
#
-# Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+# Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -771,12 +771,12 @@ def write_vcd_trace(steps_start, steps_stop, index):
if gotread:
buf = data[:]
- for i in reversed(range(len(tdata))):
+ for ii in reversed(range(len(tdata))):
for k in range(width):
- if tdata[i][k] == "x":
- tdata[i][k] = buf[k]
+ if tdata[ii][k] == "x":
+ tdata[ii][k] = buf[k]
else:
- buf[k] = tdata[i][k]
+ buf[k] = tdata[ii][k]
if not asyncwr:
tdata.append(data[:])
diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py
index 516091011..d73a875ba 100644
--- a/backends/smt2/smtio.py
+++ b/backends/smt2/smtio.py
@@ -1,7 +1,7 @@
#
# yosys -- Yosys Open SYnthesis Suite
#
-# Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+# Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -203,14 +203,14 @@ class SmtIo:
print('timeout option is not supported for mathsat.')
sys.exit(1)
- if self.solver == "boolector":
+ if self.solver in ["boolector", "bitwuzla"]:
if self.noincr:
- self.popen_vargs = ['boolector', '--smt2'] + self.solver_opts
+ self.popen_vargs = [self.solver, '--smt2'] + self.solver_opts
else:
- self.popen_vargs = ['boolector', '--smt2', '-i'] + self.solver_opts
+ self.popen_vargs = [self.solver, '--smt2', '-i'] + self.solver_opts
self.unroll = True
if self.timeout != 0:
- print('timeout option is not supported for boolector.')
+ print('timeout option is not supported for %s.' % self.solver)
sys.exit(1)
if self.solver == "abc":
@@ -1010,7 +1010,7 @@ class SmtOpts:
def helpmsg(self):
return """
-s <solver>
- set SMT solver: z3, yices, boolector, cvc4, mathsat, dummy
+ set SMT solver: z3, yices, boolector, bitwuzla, cvc4, mathsat, dummy
default: yices
-S <opt>
diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc
index e41582fea..7d4f94adc 100644
--- a/backends/smv/smv.cc
+++ b/backends/smv/smv.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -578,7 +578,7 @@ struct SmvWorker
log_error("Unsupported cell type %s for cell %s.%s -- please run `dffunmap` before `write_smv`.\n",
log_id(cell->type), log_id(module), log_id(cell));
}
- if (cell->type.in(ID($adff), ID($adffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF") {
+ if (cell->type.in(ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($dffsr), ID($dffsre)) || cell->type.str().substr(0, 5) == "$_DFF" || cell->type.str().substr(0, 7) == "$_ALDFF") {
log_error("Unsupported cell type %s for cell %s.%s -- please run `async2sync; dffunmap` or `clk2fflogic` before `write_smv`.\n",
log_id(cell->type), log_id(module), log_id(cell));
}
@@ -741,6 +741,11 @@ struct SmvBackend : public Backend {
log_header(design, "Executing SMV backend.\n");
+ log_push();
+ Pass::call(design, "bmuxmap");
+ Pass::call(design, "demuxmap");
+ log_pop();
+
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
{
diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc
index ca5c680c9..f260276eb 100644
--- a/backends/spice/spice.cc
+++ b/backends/spice/spice.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/backends/table/table.cc b/backends/table/table.cc
index 77642ccbd..2bf64e7b1 100644
--- a/backends/table/table.cc
+++ b/backends/table/table.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc
index 165ce1ea4..aa1d4558c 100644
--- a/backends/verilog/verilog_backend.cc
+++ b/backends/verilog/verilog_backend.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -44,6 +44,7 @@ std::string auto_prefix, extmem_prefix;
RTLIL::Module *active_module;
dict<RTLIL::SigBit, RTLIL::State> active_initdata;
SigMap active_sigmap;
+IdString initial_id;
void reset_auto_counter_id(RTLIL::IdString id, bool may_rename)
{
@@ -357,7 +358,8 @@ void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool no_decima
void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig)
{
if (GetSize(sig) == 0) {
- f << "\"\"";
+ // See IEEE 1364-2005 Clause 5.1.14.
+ f << "{0{1'b0}}";
return;
}
if (sig.is_chunk()) {
@@ -430,7 +432,7 @@ void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire)
dump_const(f, wire->attributes.at(ID::init));
}
f << stringf(";\n");
- } else if (!wire->port_input && !wire->port_output)
+ } else
f << stringf("%s" "wire%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str());
#endif
}
@@ -504,9 +506,24 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
int start = init.addr.as_int();
for (int i=0; i<words; i++)
{
- f << stringf("%s" " %s[%d] = ", indent.c_str(), mem_id.c_str(), i + start);
- dump_const(f, init.data.extract(i*mem.width, mem.width));
- f << stringf(";\n");
+ for (int j = 0; j < mem.width; j++)
+ {
+ if (init.en[j] != State::S1)
+ continue;
+
+ int start_j = j, width = 1;
+
+ while (j+1 < mem.width && init.en[j+1] == State::S1)
+ j++, width++;
+
+ if (width == mem.width) {
+ f << stringf("%s" " %s[%d] = ", indent.c_str(), mem_id.c_str(), i + start);
+ } else {
+ f << stringf("%s" " %s[%d][%d:%d] = ", indent.c_str(), mem_id.c_str(), i + start, j, start_j);
+ }
+ dump_const(f, init.data.extract(i*mem.width+start_j, width));
+ f << stringf(";\n");
+ }
}
}
f << stringf("%s" "end\n", indent.c_str());
@@ -515,6 +532,8 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
// create a map : "edge clk" -> expressions within that clock domain
dict<std::string, std::vector<std::string>> clk_to_lof_body;
+ dict<std::string, std::string> clk_to_arst_cond;
+ dict<std::string, std::vector<std::string>> clk_to_arst_body;
clk_to_lof_body[""] = std::vector<std::string>();
std::string clk_domain_str;
// create a list of reg declarations
@@ -529,10 +548,27 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
std::ostringstream os;
dump_sigspec(os, port.clk);
clk_domain_str = stringf("%sedge %s", port.clk_polarity ? "pos" : "neg", os.str().c_str());
- if( clk_to_lof_body.count(clk_domain_str) == 0 )
- clk_to_lof_body[clk_domain_str] = std::vector<std::string>();
+ if (port.arst != State::S0) {
+ std::ostringstream os2;
+ dump_sigspec(os2, port.arst);
+ clk_domain_str += stringf(", posedge %s", os2.str().c_str());
+ clk_to_arst_cond[clk_domain_str] = os2.str();
+ }
}
- if (!port.transparent)
+
+ // Decide how to represent the transparency; same idea as Mem::extract_rdff.
+ bool trans_use_addr = true;
+ for (auto bit : port.transparency_mask)
+ if (!bit)
+ trans_use_addr = false;
+
+ if (GetSize(mem.wr_ports) == 0)
+ trans_use_addr = false;
+
+ if (port.en != State::S1 || port.srst != State::S0 || port.arst != State::S0 || !port.init_value.is_fully_undef())
+ trans_use_addr = false;
+
+ if (!trans_use_addr)
{
// for clocked read ports make something like:
// reg [..] temp_id;
@@ -541,19 +577,148 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
// assign r_data = temp_id;
std::string temp_id = next_auto_id();
lof_reg_declarations.push_back( stringf("reg [%d:0] %s;\n", port.data.size() - 1, temp_id.c_str()) );
- {
+
+ bool has_indent = false;
+
+ if (port.arst != State::S0) {
std::ostringstream os;
- if (port.en != RTLIL::SigBit(true))
- {
- os << stringf("if (");
- dump_sigspec(os, port.en);
- os << stringf(") ");
+ os << stringf("%s <= ", temp_id.c_str());
+ dump_sigspec(os, port.arst_value);
+ os << ";\n";
+ clk_to_arst_body[clk_domain_str].push_back(os.str());
+ }
+
+ if (port.srst != State::S0 && !port.ce_over_srst) {
+ std::ostringstream os;
+ os << stringf("if (");
+ dump_sigspec(os, port.srst);
+ os << stringf(")\n");
+ clk_to_lof_body[clk_domain_str].push_back(os.str());
+ std::ostringstream os2;
+ os2 << stringf("%s" "%s <= ", indent.c_str(), temp_id.c_str());
+ dump_sigspec(os2, port.srst_value);
+ os2 << ";\n";
+ clk_to_lof_body[clk_domain_str].push_back(os2.str());
+ std::ostringstream os3;
+ if (port.en == State::S1) {
+ os3 << "else begin\n";
+ } else {
+ os3 << "else if (";
+ dump_sigspec(os3, port.en);
+ os3 << ") begin\n";
}
- os << stringf("%s <= %s[", temp_id.c_str(), mem_id.c_str());
- dump_sigspec(os, port.addr);
+ clk_to_lof_body[clk_domain_str].push_back(os3.str());
+ has_indent = true;
+ } else if (port.en != State::S1) {
+ std::ostringstream os;
+ os << stringf("if (");
+ dump_sigspec(os, port.en);
+ os << stringf(") begin\n");
+ clk_to_lof_body[clk_domain_str].push_back(os.str());
+ has_indent = true;
+ }
+
+ for (int sub = 0; sub < (1 << port.wide_log2); sub++)
+ {
+ SigSpec addr = port.sub_addr(sub);
+ std::ostringstream os;
+ if (has_indent)
+ os << indent;
+ os << temp_id;
+ if (port.wide_log2)
+ os << stringf("[%d:%d]", (sub + 1) * mem.width - 1, sub * mem.width);
+ os << stringf(" <= %s[", mem_id.c_str());
+ dump_sigspec(os, addr);
os << stringf("];\n");
clk_to_lof_body[clk_domain_str].push_back(os.str());
}
+
+ for (int i = 0; i < GetSize(mem.wr_ports); i++) {
+ auto &wport = mem.wr_ports[i];
+ if (!port.transparency_mask[i] && !port.collision_x_mask[i])
+ continue;
+ int min_wide_log2 = std::min(port.wide_log2, wport.wide_log2);
+ int max_wide_log2 = std::max(port.wide_log2, wport.wide_log2);
+ bool wide_write = wport.wide_log2 > port.wide_log2;
+ for (int sub = 0; sub < (1 << max_wide_log2); sub += (1 << min_wide_log2)) {
+ SigSpec raddr = port.addr;
+ SigSpec waddr = wport.addr;
+ if (wide_write)
+ waddr = wport.sub_addr(sub);
+ else
+ raddr = port.sub_addr(sub);
+ int pos = 0;
+ int ewidth = mem.width << min_wide_log2;
+ int wsub = wide_write ? sub : 0;
+ int rsub = wide_write ? 0 : sub;
+ while (pos < ewidth) {
+ int epos = pos;
+ while (epos < ewidth && wport.en[epos + wsub * mem.width] == wport.en[pos + wsub * mem.width])
+ epos++;
+
+ std::ostringstream os;
+ if (has_indent)
+ os << indent;
+ os << "if (";
+ dump_sigspec(os, wport.en[pos + wsub * mem.width]);
+ if (raddr != waddr) {
+ os << " && ";
+ dump_sigspec(os, raddr);
+ os << " == ";
+ dump_sigspec(os, waddr);
+ }
+ os << ")\n";
+ clk_to_lof_body[clk_domain_str].push_back(os.str());
+
+ std::ostringstream os2;
+ if (has_indent)
+ os2 << indent;
+ os2 << indent;
+ os2 << temp_id;
+ if (epos-pos != GetSize(port.data))
+ os2 << stringf("[%d:%d]", rsub * mem.width + epos-1, rsub * mem.width + pos);
+ os2 << " <= ";
+ if (port.transparency_mask[i])
+ dump_sigspec(os2, wport.data.extract(wsub * mem.width + pos, epos-pos));
+ else
+ dump_sigspec(os2, Const(State::Sx, epos - pos));
+ os2 << ";\n";
+ clk_to_lof_body[clk_domain_str].push_back(os2.str());
+
+ pos = epos;
+ }
+ }
+ }
+
+ if (port.srst != State::S0 && port.ce_over_srst)
+ {
+ std::ostringstream os;
+ if (has_indent)
+ os << indent;
+ os << stringf("if (");
+ dump_sigspec(os, port.srst);
+ os << stringf(")\n");
+ clk_to_lof_body[clk_domain_str].push_back(os.str());
+ std::ostringstream os2;
+ if (has_indent)
+ os2 << indent;
+ os2 << stringf("%s" "%s <= ", indent.c_str(), temp_id.c_str());
+ dump_sigspec(os2, port.srst_value);
+ os2 << ";\n";
+ clk_to_lof_body[clk_domain_str].push_back(os2.str());
+ }
+
+ if (has_indent)
+ clk_to_lof_body[clk_domain_str].push_back("end\n");
+
+ if (!port.init_value.is_fully_undef())
+ {
+ std::ostringstream os;
+ dump_sigspec(os, port.init_value);
+ std::string line = stringf("initial %s = %s;\n", temp_id.c_str(), os.str().c_str());
+ clk_to_lof_body[""].push_back(line);
+ }
+
{
std::ostringstream os;
dump_sigspec(os, port.data);
@@ -569,73 +734,153 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
// temp_id <= r_addr;
// assign r_data = array_reg[temp_id];
std::string temp_id = next_auto_id();
- lof_reg_declarations.push_back( stringf("reg [%d:0] %s;\n", port.addr.size() - 1, temp_id.c_str()) );
+ lof_reg_declarations.push_back( stringf("reg [%d:0] %s;\n", port.addr.size() - 1 - port.wide_log2, temp_id.c_str()) );
{
std::ostringstream os;
- dump_sigspec(os, port.addr);
+ dump_sigspec(os, port.addr.extract_end(port.wide_log2));
std::string line = stringf("%s <= %s;\n", temp_id.c_str(), os.str().c_str());
clk_to_lof_body[clk_domain_str].push_back(line);
}
+ for (int sub = 0; sub < (1 << port.wide_log2); sub++)
{
std::ostringstream os;
- dump_sigspec(os, port.data);
- std::string line = stringf("assign %s = %s[%s];\n", os.str().c_str(), mem_id.c_str(), temp_id.c_str());
- clk_to_lof_body[""].push_back(line);
+ os << "assign ";
+ dump_sigspec(os, port.data.extract(sub * mem.width, mem.width));
+ os << stringf(" = %s[", mem_id.c_str());;
+ if (port.wide_log2) {
+ Const addr_lo;
+ for (int i = 0; i < port.wide_log2; i++)
+ addr_lo.bits.push_back(State(sub >> i & 1));
+ os << "{";
+ os << temp_id;
+ os << ", ";
+ dump_const(os, addr_lo);
+ os << "}";
+ } else {
+ os << temp_id;
+ }
+ os << "];\n";
+ clk_to_lof_body[""].push_back(os.str());
}
}
} else {
// for non-clocked read-ports make something like:
// assign r_data = array_reg[r_addr];
- std::ostringstream os, os2;
- dump_sigspec(os, port.data);
- dump_sigspec(os2, port.addr);
- std::string line = stringf("assign %s = %s[%s];\n", os.str().c_str(), mem_id.c_str(), os2.str().c_str());
- clk_to_lof_body[""].push_back(line);
+ for (int sub = 0; sub < (1 << port.wide_log2); sub++)
+ {
+ SigSpec addr = port.sub_addr(sub);
+
+ std::ostringstream os, os2;
+ dump_sigspec(os, port.data.extract(sub * mem.width, mem.width));
+ dump_sigspec(os2, addr);
+ std::string line = stringf("assign %s = %s[%s];\n", os.str().c_str(), mem_id.c_str(), os2.str().c_str());
+ clk_to_lof_body[""].push_back(line);
+ }
}
}
- // write ports
- for (auto &port : mem.wr_ports)
+ // Write ports. Those are messy because we try to preserve priority, as much as we can:
+ //
+ // 1. We split all ports into several disjoint processes.
+ // 2. If a port has priority over another port, the two ports need to share
+ // a process, so that priority can be reconstructed on the other end.
+ // 3. We want each process to be as small as possible, to avoid extra
+ // priorities inferred on the other end.
+ pool<int> wr_ports_done;
+ for (int ridx = 0; ridx < GetSize(mem.wr_ports); ridx++)
{
+ if (wr_ports_done.count(ridx))
+ continue;
+
+ auto &root = mem.wr_ports[ridx];
+
+ // Start from a root.
+ pool<int> wr_ports_now;
+ wr_ports_now.insert(ridx);
+
+ // Transitively fill list of ports in this process by following priority edges.
+ while (true)
{
- std::ostringstream os;
- dump_sigspec(os, port.clk);
- clk_domain_str = stringf("%sedge %s", port.clk_polarity ? "pos" : "neg", os.str().c_str());
- if( clk_to_lof_body.count(clk_domain_str) == 0 )
- clk_to_lof_body[clk_domain_str] = std::vector<std::string>();
+ bool changed = false;
+
+ for (int i = 0; i < GetSize(mem.wr_ports); i++)
+ for (int j = 0; j < i; j++)
+ if (mem.wr_ports[i].priority_mask[j])
+ {
+ if (wr_ports_now.count(i) && !wr_ports_now.count(j)) {
+ wr_ports_now.insert(j);
+ changed = true;
+ }
+ if (!wr_ports_now.count(i) && wr_ports_now.count(j)) {
+ wr_ports_now.insert(i);
+ changed = true;
+ }
+ }
+
+ if (!changed)
+ break;
}
- // make something like:
- // always @(posedge clk)
- // if (wr_en_bit) memid[w_addr][??] <= w_data[??];
- // ...
- for (int i = 0; i < GetSize(port.en); i++)
- {
- int start_i = i, width = 1;
- SigBit wen_bit = port.en[i];
- while (i+1 < GetSize(port.en) && active_sigmap(port.en[i+1]) == active_sigmap(wen_bit))
- i++, width++;
+ if (root.clk_enable) {
+ f << stringf("%s" "always%s @(%sedge ", indent.c_str(), systemverilog ? "_ff" : "", root.clk_polarity ? "pos" : "neg");
+ dump_sigspec(f, root.clk);
+ f << ") begin\n";
+ } else {
+ f << stringf("%s" "always%s begin\n", indent.c_str(), systemverilog ? "_latch" : " @*");
+ }
- if (wen_bit == State::S0)
+ for (int pidx = 0; pidx < GetSize(mem.wr_ports); pidx++)
+ {
+ if (!wr_ports_now.count(pidx))
continue;
+ wr_ports_done.insert(pidx);
- std::ostringstream os;
- if (wen_bit != State::S1)
+ auto &port = mem.wr_ports[pidx];
+ log_assert(port.clk_enable == root.clk_enable);
+ if (port.clk_enable) {
+ log_assert(port.clk == root.clk);
+ log_assert(port.clk_polarity == root.clk_polarity);
+ }
+
+ // make something like:
+ // always @(posedge clk)
+ // if (wr_en_bit) memid[w_addr][??] <= w_data[??];
+ // ...
+ for (int sub = 0; sub < (1 << port.wide_log2); sub++)
{
- os << stringf("if (");
- dump_sigspec(os, wen_bit);
- os << stringf(") ");
+ SigSpec addr = port.sub_addr(sub);
+ for (int i = 0; i < mem.width; i++)
+ {
+ int start_i = i, width = 1;
+ SigBit wen_bit = port.en[sub * mem.width + i];
+
+ while (i+1 < mem.width && active_sigmap(port.en[sub * mem.width + i+1]) == active_sigmap(wen_bit))
+ i++, width++;
+
+ if (wen_bit == State::S0)
+ continue;
+
+ f << stringf("%s%s", indent.c_str(), indent.c_str());
+ if (wen_bit != State::S1)
+ {
+ f << stringf("if (");
+ dump_sigspec(f, wen_bit);
+ f << stringf(")\n");
+ f << stringf("%s%s%s", indent.c_str(), indent.c_str(), indent.c_str());
+ }
+ f << stringf("%s[", mem_id.c_str());
+ dump_sigspec(f, addr);
+ if (width == GetSize(port.en))
+ f << stringf("] <= ");
+ else
+ f << stringf("][%d:%d] <= ", i, start_i);
+ dump_sigspec(f, port.data.extract(sub * mem.width + start_i, width));
+ f << stringf(";\n");
+ }
}
- os << stringf("%s[", mem_id.c_str());
- dump_sigspec(os, port.addr);
- if (width == GetSize(port.en))
- os << stringf("] <= ");
- else
- os << stringf("][%d:%d] <= ", i, start_i);
- dump_sigspec(os, port.data.extract(start_i, width));
- os << stringf(";\n");
- clk_to_lof_body[clk_domain_str].push_back(os.str());
}
+
+ f << stringf("%s" "end\n", indent.c_str());
}
// Output Verilog that looks something like this:
// reg [..] _3_;
@@ -668,8 +913,19 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
if( clk_domain != "")
{
f << stringf("%s" "always%s @(%s) begin\n", indent.c_str(), systemverilog ? "_ff" : "", clk_domain.c_str());
- for(auto &line : lof_lines)
- f << stringf("%s%s" "%s", indent.c_str(), indent.c_str(), line.c_str());
+ bool has_arst = clk_to_arst_cond.count(clk_domain) != 0;
+ if (has_arst) {
+ f << stringf("%s%s" "if (%s) begin\n", indent.c_str(), indent.c_str(), clk_to_arst_cond[clk_domain].c_str());
+ for(auto &line : clk_to_arst_body[clk_domain])
+ f << stringf("%s%s%s" "%s", indent.c_str(), indent.c_str(), indent.c_str(), line.c_str());
+ f << stringf("%s%s" "end else begin\n", indent.c_str(), indent.c_str());
+ for(auto &line : lof_lines)
+ f << stringf("%s%s%s" "%s", indent.c_str(), indent.c_str(), indent.c_str(), line.c_str());
+ f << stringf("%s%s" "end\n", indent.c_str(), indent.c_str());
+ } else {
+ for(auto &line : lof_lines)
+ f << stringf("%s%s" "%s", indent.c_str(), indent.c_str(), line.c_str());
+ }
f << stringf("%s" "end\n", indent.c_str());
}
else
@@ -1144,7 +1400,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
FfData ff(nullptr, cell);
// $ff / $_FF_ cell: not supported.
- if (ff.has_d && !ff.has_clk && !ff.has_en)
+ if (ff.has_gclk)
return false;
std::string reg_name = cellname(cell);
@@ -1165,17 +1421,19 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
for (int i = 0; i < chunks; i++)
{
- SigSpec sig_d;
+ SigSpec sig_d, sig_ad;
Const val_arst, val_srst;
- std::string reg_bit_name, sig_set_name, sig_clr_name, sig_arst_name;
+ std::string reg_bit_name, sig_set_name, sig_clr_name, sig_arst_name, sig_aload_name;
if (chunky) {
reg_bit_name = stringf("%s[%d]", reg_name.c_str(), i);
- if (ff.has_d)
+ if (ff.has_gclk || ff.has_clk)
sig_d = ff.sig_d[i];
+ if (ff.has_aload)
+ sig_ad = ff.sig_ad[i];
} else {
reg_bit_name = reg_name;
- if (ff.has_d)
- sig_d = ff.sig_d;
+ sig_d = ff.sig_d;
+ sig_ad = ff.sig_ad;
}
if (ff.has_arst)
val_arst = chunky ? ff.val_arst[i] : ff.val_arst;
@@ -1183,28 +1441,38 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
val_srst = chunky ? ff.val_srst[i] : ff.val_srst;
// If there are constants in the sensitivity list, replace them with an intermediate wire
- if (ff.has_sr) {
- if (ff.sig_set[i].wire == NULL)
- {
- sig_set_name = next_auto_id();
- f << stringf("%s" "wire %s = ", indent.c_str(), sig_set_name.c_str());
- dump_const(f, ff.sig_set[i].data);
- f << stringf(";\n");
- }
- if (ff.sig_clr[i].wire == NULL)
- {
- sig_clr_name = next_auto_id();
- f << stringf("%s" "wire %s = ", indent.c_str(), sig_clr_name.c_str());
- dump_const(f, ff.sig_clr[i].data);
- f << stringf(";\n");
- }
- } else if (ff.has_arst) {
- if (ff.sig_arst[i].wire == NULL)
- {
- sig_arst_name = next_auto_id();
- f << stringf("%s" "wire %s = ", indent.c_str(), sig_arst_name.c_str());
- dump_const(f, ff.sig_arst[i].data);
- f << stringf(";\n");
+ if (ff.has_clk) {
+ if (ff.has_sr) {
+ if (ff.sig_set[i].wire == NULL)
+ {
+ sig_set_name = next_auto_id();
+ f << stringf("%s" "wire %s = ", indent.c_str(), sig_set_name.c_str());
+ dump_const(f, ff.sig_set[i].data);
+ f << stringf(";\n");
+ }
+ if (ff.sig_clr[i].wire == NULL)
+ {
+ sig_clr_name = next_auto_id();
+ f << stringf("%s" "wire %s = ", indent.c_str(), sig_clr_name.c_str());
+ dump_const(f, ff.sig_clr[i].data);
+ f << stringf(";\n");
+ }
+ } else if (ff.has_arst) {
+ if (ff.sig_arst[0].wire == NULL)
+ {
+ sig_arst_name = next_auto_id();
+ f << stringf("%s" "wire %s = ", indent.c_str(), sig_arst_name.c_str());
+ dump_const(f, ff.sig_arst[0].data);
+ f << stringf(";\n");
+ }
+ } else if (ff.has_aload) {
+ if (ff.sig_aload[0].wire == NULL)
+ {
+ sig_aload_name = next_auto_id();
+ f << stringf("%s" "wire %s = ", indent.c_str(), sig_aload_name.c_str());
+ dump_const(f, ff.sig_aload[0].data);
+ f << stringf(";\n");
+ }
}
}
@@ -1226,13 +1494,18 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
f << stringf("%s", sig_clr_name.c_str());
else
dump_sigspec(f, ff.sig_clr[i]);
-
} else if (ff.has_arst) {
f << stringf(", %sedge ", ff.pol_arst ? "pos" : "neg");
- if (ff.sig_arst[i].wire == NULL)
+ if (ff.sig_arst[0].wire == NULL)
f << stringf("%s", sig_arst_name.c_str());
else
dump_sigspec(f, ff.sig_arst);
+ } else if (ff.has_aload) {
+ f << stringf(", %sedge ", ff.pol_aload ? "pos" : "neg");
+ if (ff.sig_aload[0].wire == NULL)
+ f << stringf("%s", sig_aload_name.c_str());
+ else
+ dump_sigspec(f, ff.sig_aload);
}
f << stringf(")\n");
@@ -1253,7 +1526,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
f << stringf("%s" " else ", indent.c_str());
} else if (ff.has_arst) {
f << stringf("if (%s", ff.pol_arst ? "" : "!");
- if (ff.sig_arst[i].wire == NULL)
+ if (ff.sig_arst[0].wire == NULL)
f << stringf("%s", sig_arst_name.c_str());
else
dump_sigspec(f, ff.sig_arst);
@@ -1261,11 +1534,21 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
dump_sigspec(f, val_arst);
f << stringf(";\n");
f << stringf("%s" " else ", indent.c_str());
+ } else if (ff.has_aload) {
+ f << stringf("if (%s", ff.pol_aload ? "" : "!");
+ if (ff.sig_aload[0].wire == NULL)
+ f << stringf("%s", sig_aload_name.c_str());
+ else
+ dump_sigspec(f, ff.sig_aload);
+ f << stringf(") %s <= ", reg_bit_name.c_str());
+ dump_sigspec(f, sig_ad);
+ f << stringf(";\n");
+ f << stringf("%s" " else ", indent.c_str());
}
- if (ff.has_srst && ff.has_en && ff.ce_over_srst) {
- f << stringf("if (%s", ff.pol_en ? "" : "!");
- dump_sigspec(f, ff.sig_en);
+ if (ff.has_srst && ff.has_ce && ff.ce_over_srst) {
+ f << stringf("if (%s", ff.pol_ce ? "" : "!");
+ dump_sigspec(f, ff.sig_ce);
f << stringf(")\n");
f << stringf("%s" " if (%s", indent.c_str(), ff.pol_srst ? "" : "!");
dump_sigspec(f, ff.sig_srst);
@@ -1282,9 +1565,9 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
f << stringf(";\n");
f << stringf("%s" " else ", indent.c_str());
}
- if (ff.has_en) {
- f << stringf("if (%s", ff.pol_en ? "" : "!");
- dump_sigspec(f, ff.sig_en);
+ if (ff.has_ce) {
+ f << stringf("if (%s", ff.pol_ce ? "" : "!");
+ dump_sigspec(f, ff.sig_ce);
f << stringf(") ");
}
}
@@ -1306,7 +1589,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
f << stringf("%s" " else if (%s", indent.c_str(), ff.pol_set ? "" : "!");
dump_sigspec(f, ff.sig_set[i]);
f << stringf(") %s = 1'b1;\n", reg_bit_name.c_str());
- if (ff.has_d)
+ if (ff.has_aload)
f << stringf("%s" " else ", indent.c_str());
} else if (ff.has_arst) {
f << stringf("if (%s", ff.pol_arst ? "" : "!");
@@ -1314,14 +1597,14 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
f << stringf(") %s = ", reg_bit_name.c_str());
dump_sigspec(f, val_arst);
f << stringf(";\n");
- if (ff.has_d)
+ if (ff.has_aload)
f << stringf("%s" " else ", indent.c_str());
}
- if (ff.has_d) {
- f << stringf("if (%s", ff.pol_en ? "" : "!");
- dump_sigspec(f, ff.sig_en);
+ if (ff.has_aload) {
+ f << stringf("if (%s", ff.pol_aload ? "" : "!");
+ dump_sigspec(f, ff.sig_aload);
f << stringf(") %s = ", reg_bit_name.c_str());
- dump_sigspec(f, sig_d);
+ dump_sigspec(f, sig_ad);
f << stringf(";\n");
}
}
@@ -1464,7 +1747,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell)
{
// Handled by dump_memory
- if (cell->type.in(ID($mem), ID($memwr), ID($memrd), ID($meminit)))
+ if (cell->is_mem_cell())
return;
if (cell->type[0] == '$' && !noexpr) {
@@ -1662,7 +1945,7 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo
f << stringf("%s" "always%s begin\n", indent.c_str(), systemverilog ? "_comb" : " @*");
if (!systemverilog)
- f << indent + " " << "if (" << id("\\initial") << ") begin end\n";
+ f << indent + " " << "if (" << id(initial_id) << ") begin end\n";
dump_case_body(f, indent, &proc->root_case, true);
std::string backup_indent = indent;
@@ -1781,6 +2064,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
dump_attributes(f, indent, module->attributes, '\n', /*modattr=*/true);
f << stringf("%s" "module %s(", indent.c_str(), id(module->name, false).c_str());
bool keep_running = true;
+ int cnt = 0;
for (int port_id = 1; keep_running; port_id++) {
keep_running = false;
for (auto wire : module->wires()) {
@@ -1789,14 +2073,16 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
f << stringf(", ");
f << stringf("%s", id(wire->name).c_str());
keep_running = true;
+ if (cnt==20) { f << stringf("\n"); cnt = 0; } else cnt++;
continue;
}
}
}
f << stringf(");\n");
-
- if (!systemverilog && !module->processes.empty())
- f << indent + " " << "reg " << id("\\initial") << " = 0;\n";
+ if (!systemverilog && !module->processes.empty()) {
+ initial_id = NEW_ID;
+ f << indent + " " << "reg " << id(initial_id) << " = 0;\n";
+ }
for (auto w : module->wires())
dump_wire(f, indent + " ", w);
@@ -2014,6 +2300,12 @@ struct VerilogBackend : public Backend {
extmem_prefix = filename.substr(0, filename.rfind('.'));
}
+ log_push();
+ Pass::call(design, "bmuxmap");
+ Pass::call(design, "demuxmap");
+ Pass::call(design, "clean_zerowidth");
+ log_pop();
+
design->sort();
*f << stringf("/* Generated by %s */\n", yosys_version_str);
diff --git a/examples/smtbmc/Makefile b/examples/smtbmc/Makefile
index 61994f942..af937ea74 100644
--- a/examples/smtbmc/Makefile
+++ b/examples/smtbmc/Makefile
@@ -1,5 +1,5 @@
-all: demo1 demo2 demo3 demo4 demo5 demo6 demo7 demo8 demo9
+all: demo1 demo2 demo3 demo4 demo5 demo6 demo7 demo8 demo9 glift_mux
demo1: demo1.smt2
yosys-smtbmc --dump-vcd demo1.vcd demo1.smt2
@@ -31,6 +31,9 @@ demo8: demo8.smt2
demo9: demo9.smt2
yosys-smtbmc -s z3 -t 1 -g demo9.smt2
+glift_mux:
+ yosys -ql glift_mux.yslog glift/mux2.ys
+
demo1.smt2: demo1.v
yosys -ql demo1.yslog -p 'read_verilog -formal demo1.v; prep -top demo1 -nordff; write_smt2 -wires demo1.smt2'
@@ -68,6 +71,7 @@ clean:
rm -f demo7.yslog demo7.smt2
rm -f demo8.yslog demo8.smt2
rm -f demo9.yslog demo9.smt2
+ rm -f glift_mux.ys
.PHONY: demo1 demo2 demo3 demo4 demo5 demo6 demo7 demo8 demo9 clean
diff --git a/examples/smtbmc/glift/C7552.v b/examples/smtbmc/glift/C7552.v
new file mode 100755
index 000000000..47a8b0d37
--- /dev/null
+++ b/examples/smtbmc/glift/C7552.v
@@ -0,0 +1,4194 @@
+module C7552_lev2(pi000, pi001, pi002, pi003, pi004, pi005, pi006, pi007, pi008, pi009,
+ pi010, pi011, pi012, pi013, pi014, pi015, pi016, pi017, pi018, pi019,
+ pi020, pi021, pi022, pi023, pi024, pi025, pi026, pi027, pi028, pi029,
+ pi030, pi031, pi032, pi033, pi034, pi035, pi036, pi037, pi038, pi039,
+ pi040, pi041, pi042, pi043, pi044, pi045, pi046, pi047, pi048, pi049,
+ pi050, pi051, pi052, pi053, pi054, pi055, pi056, pi057, pi058, pi059,
+ pi060, pi061, pi062, pi063, pi064, pi065, pi066, pi067, pi068, pi069,
+ pi070, pi071, pi072, pi073, pi074, pi075, pi076, pi077, pi078, pi079,
+ pi080, pi081, pi082, pi083, pi084, pi085, pi086, pi087, pi088, pi089,
+ pi090, pi091, pi092, pi093, pi094, pi095, pi096, pi097, pi098, pi099,
+ pi100, pi101, pi102, pi103, pi104, pi105, pi106, pi107, pi108, pi109,
+ pi110, pi111, pi112, pi113, pi114, pi115, pi116, pi117, pi118, pi119,
+ pi120, pi121, pi122, pi123, pi124, pi125, pi126, pi127, pi128, pi129,
+ pi130, pi131, pi132, pi133, pi134, pi135, pi136, pi137, pi138, pi139,
+ pi140, pi141, pi142, pi143, pi144, pi145, pi146, pi147, pi148, pi149,
+ pi150, pi151, pi152, pi153, pi154, pi155, pi156, pi157, pi158, pi159,
+ pi160, pi161, pi162, pi163, pi164, pi165, pi166, pi167, pi168, pi169,
+ pi170, pi171, pi172, pi173, pi174, pi175, pi176, pi177, pi178, pi179,
+ pi180, pi181, pi182, pi183, pi184, pi185, pi186, pi187, pi188, pi189,
+ pi190, pi191, pi192, pi193, pi194, pi195, pi196, pi197, pi198, pi199,
+ pi200, pi201, pi202, pi203, pi204, pi205, pi206, po000, po001, po002,
+ po003, po004, po005, po006, po007, po008, po009, po010, po011, po012,
+ po013, po014, po015, po016, po017, po018, po019, po020, po021, po022,
+ po023, po024, po025, po026, po027, po028, po029, po030, po031, po032,
+ po033, po034, po035, po036, po037, po038, po039, po040, po041, po042,
+ po043, po044, po045, po046, po047, po048, po049, po050, po051, po052,
+ po053, po054, po055, po056, po057, po058, po059, po060, po061, po062,
+ po063, po064, po065, po066, po067, po068, po069, po070, po071, po072,
+ po073, po074, po075, po076, po077, po078, po079, po080, po081, po082,
+ po083, po084, po085, po086, po087, po088, po089, po090, po091, po092,
+ po093, po094, po095, po096, po097, po098, po099, po100, po101, po102,
+ po103, po104, po105, po106, po107);
+
+input pi000, pi001, pi002, pi003, pi004, pi005, pi006, pi007, pi008, pi009,
+ pi010, pi011, pi012, pi013, pi014, pi015, pi016, pi017, pi018, pi019,
+ pi020, pi021, pi022, pi023, pi024, pi025, pi026, pi027, pi028, pi029,
+ pi030, pi031, pi032, pi033, pi034, pi035, pi036, pi037, pi038, pi039,
+ pi040, pi041, pi042, pi043, pi044, pi045, pi046, pi047, pi048, pi049,
+ pi050, pi051, pi052, pi053, pi054, pi055, pi056, pi057, pi058, pi059,
+ pi060, pi061, pi062, pi063, pi064, pi065, pi066, pi067, pi068, pi069,
+ pi070, pi071, pi072, pi073, pi074, pi075, pi076, pi077, pi078, pi079,
+ pi080, pi081, pi082, pi083, pi084, pi085, pi086, pi087, pi088, pi089,
+ pi090, pi091, pi092, pi093, pi094, pi095, pi096, pi097, pi098, pi099,
+ pi100, pi101, pi102, pi103, pi104, pi105, pi106, pi107, pi108, pi109,
+ pi110, pi111, pi112, pi113, pi114, pi115, pi116, pi117, pi118, pi119,
+ pi120, pi121, pi122, pi123, pi124, pi125, pi126, pi127, pi128, pi129,
+ pi130, pi131, pi132, pi133, pi134, pi135, pi136, pi137, pi138, pi139,
+ pi140, pi141, pi142, pi143, pi144, pi145, pi146, pi147, pi148, pi149,
+ pi150, pi151, pi152, pi153, pi154, pi155, pi156, pi157, pi158, pi159,
+ pi160, pi161, pi162, pi163, pi164, pi165, pi166, pi167, pi168, pi169,
+ pi170, pi171, pi172, pi173, pi174, pi175, pi176, pi177, pi178, pi179,
+ pi180, pi181, pi182, pi183, pi184, pi185, pi186, pi187, pi188, pi189,
+ pi190, pi191, pi192, pi193, pi194, pi195, pi196, pi197, pi198, pi199,
+ pi200, pi201, pi202, pi203, pi204, pi205, pi206;
+
+output po000, po001, po002, po003, po004, po005, po006, po007, po008, po009,
+ po010, po011, po012, po013, po014, po015, po016, po017, po018, po019,
+ po020, po021, po022, po023, po024, po025, po026, po027, po028, po029,
+ po030, po031, po032, po033, po034, po035, po036, po037, po038, po039,
+ po040, po041, po042, po043, po044, po045, po046, po047, po048, po049,
+ po050, po051, po052, po053, po054, po055, po056, po057, po058, po059,
+ po060, po061, po062, po063, po064, po065, po066, po067, po068, po069,
+ po070, po071, po072, po073, po074, po075, po076, po077, po078, po079,
+ po080, po081, po082, po083, po084, po085, po086, po087, po088, po089,
+ po090, po091, po092, po093, po094, po095, po096, po097, po098, po099,
+ po100, po101, po102, po103, po104, po105, po106, po107;
+
+wire n2822, n2823, n2824, n2825, n2826, n2827, n2828, n2829, n2830, n2831,
+ n2832, n2833, n2834, n2835, n2836, n2837, n2838, n2839, n2840, n2841,
+ n2842, n2843, n2844, n2845, n2846, n2847, n2848, n2849, n2850, n2851,
+ n2852, n2853, n2854, n2855, n2856, n2857, n2858, n2859, n2860, n2861,
+ n2862, n2863, n2864, n2865, n2866, n2867, n2868, n2869, n2870, n2871,
+ n2872, n2873, n2874, n2875, n2876, n2877, n2878, n2879, n2880, n2881,
+ n2882, n2883, n2884, n2885, n2886, n2887, n2888, n2889, n2890, n2891,
+ n2892, n2893, n2894, n2895, n2896, n2897, n2898, n2899, n2900, n2901,
+ n2902, n2903, n2904, n2905, n2906, n2907, n2908, n2909, n2910, n2911,
+ n2912, n2913, n2914, n2915, n2916, n2917, n2918, n2919, n2920, n2921,
+ n2922, n2923, n2924, n2925, n2926, n2927, n2928, n2929, n2930, n2931,
+ n2932, n2933, n2934, n2935, n2936, n2937, n2938, n2939, n2940, n2941,
+ n2942, n2943, n2944, n2945, n2946, n2947, n2948, n2949, n2950, n2951,
+ n2952, n2953, n2954, n2955, n2956, n2957, n2958, n2959, n2960, n2961,
+ n2962, n2963, n2964, n2965, n2966, n2967, n2968, n2969, n2970, n2971,
+ n2972, n2973, n2974, n2975, n2976, n2977, n2978, n2979, n2980, n2981,
+ n2982, n2983, n2984, n2985, n2986, n2987, n2988, n2989, n2990, n2991,
+ n2992, n2993, n2994, n2995, n2996, n2997, n2998, n2999, n3000, n3001,
+ n3002, n3003, n3004, n3005, n3006, n3007, n3008, n3009, n3010, n3011,
+ n3012, n3013, n3014, n3015, n3016, n3017, n3018, n3019, n3020, n3021,
+ n3022, n3023, n3024, n3025, n3026, n3027, n3028, n3029, n3030, n3031,
+ n3032, n3033, n3034, n3035, n3036, n3037, n3038, n3039, n3040, n3041,
+ n3042, n3043, n3044, n3045, n3046, n3047, n3048, n3049, n3050, n3051,
+ n3052, n3053, n3054, n3055, n3056, n3057, n3058, n3059, n3060, n3061,
+ n3062, n3063, n3064, n3065, n3066, n3067, n3068, n3069, n3070, n3071,
+ n3072, n3073, n3074, n3075, n3076, n3077, n3078, n3079, n3080, n3081,
+ n3082, n3083, n3084, n3085, n3086, n3087, n3088, n3089, n3090, n3091,
+ n3092, n3093, n3094, n3095, n3096, n3097, n3098, n3099, n3100, n3101,
+ n3102, n3103, n3104, n3105, n3106, n3107, n3108, n3109, n3110, n3111,
+ n3112, n3113, n3114, n3115, n3116, n3117, n3118, n3119, n3120, n3121,
+ n3122, n3123, n3124, n3125, n3126, n3127, n3128, n3129, n3130, n3131,
+ n3132, n3133, n3134, n3135, n3136, n3137, n3138, n3139, n3140, n3141,
+ n3142, n3143, n3144, n3145, n3146, n3147, n3148, n3149, n3150, n3151,
+ n3152, n3153, n3154, n3155, n3156, n3157, n3158, n3159, n3160, n3161,
+ n3162, n3163, n3164, n3165, n3166, n3167, n3168, n3169, n3170, n3171,
+ n3172, n3173, n3174, n3175, n3176, n3177, n3178, n3179, n3180, n3181,
+ n3182, n3183, n3184, n3185, n3186, n3187, n3188, n3189, n3190, n3191,
+ n3192, n3193, n3194, n3195, n3196, n3197, n3198, n3199, n3200, n3201,
+ n3202, n3203, n3204, n3205, n3206, n3207, n3208, n3209, n3210, n3211,
+ n3212, n3213, n3214, n3215, n3216, n3217, n3218, n3219, n3220, n3221,
+ n3222, n3223, n3224, n3225, n3226, n3227, n3228, n3229, n3230, n3231,
+ n3232, n3233, n3234, n3235, n3236, n3237, n3238, n3239, n3240, n3241,
+ n3242, n3243, n3244, n3245, n3246, n3247, n3248, n3249, n3250, n3251,
+ n3252, n3253, n3254, n3255, n3256, n3257, n3258, n3259, n3260, n3261,
+ n3262, n3263, n3264, n3265, n3266, n3267, n3268, n3269, n3270, n3271,
+ n3272, n3273, n3274, n3275, n3276, n3277, n3278, n3279, n3280, n3281,
+ n3282, n3283, n3284, n3285, n3286, n3287, n3288, n3289, n3290, n3291,
+ n3292, n3293, n3294, n3295, n3296, n3297, n3298, n3299, n3300, n3301,
+ n3302, n3303, n3304, n3305, n3306, n3307, n3308, n3309, n3310, n3311,
+ n3312, n3313, n3314, n3315, n3316, n3317, n3318, n3319, n3320, n3321,
+ n3322, n3323, n3324, n3325, n3326, n3327, n3328, n3329, n3330, n3331,
+ n3332, n3333, n3334, n3335, n3336, n3337, n3338, n3339, n3340, n3341,
+ n3342, n3343, n3344, n3345, n3346, n3347, n3348, n3349, n3350, n3351,
+ n3352, n3353, n3354, n3355, n3356, n3357, n3358, n3359, n3360, n3361,
+ n3362, n3363, n3364, n3365, n3366, n3367, n3368, n3369, n3370, n3371,
+ n3372, n3373, n3374, n3375, n3376, n3377, n3378, n3379, n3380, n3381,
+ n3382, n3383, n3384, n3385, n3386, n3387, n3388, n3389, n3390, n3391,
+ n3392, n3393, n3394, n3395, n3396, n3397, n3398, n3399, n3400, n3401,
+ n3402, n3403, n3404, n3405, n3406, n3407, n3408, n3409, n3410, n3411,
+ n3412, n3413, n3414, n3415, n3416, n3417, n3418, n3419, n3420, n3421,
+ n3422, n3423, n3424, n3425, n3426, n3427, n3428, n3429, n3430, n3431,
+ n3432, n3433, n3434, n3435, n3436, n3437, n3438, n3439, n3440, n3441,
+ n3442, n3443, n3444, n3445, n3446, n3447, n3448, n3449, n3450, n3451,
+ n3452, n3453, n3454, n3455, n3456, n3457, n3458, n3459, n3460, n3461,
+ n3462, n3463, n3464, n3465, n3466, n3467, n3468, n3469, n3470, n3471,
+ n3472, n3473, n3474, n3475, n3476, n3477, n3478, n3479, n3480, n3481,
+ n3482, n3483, n3484, n3485, n3486, n3487, n3488, n3489, n3490, n3491,
+ n3492, n3493, n3494, n3495, n3496, n3497, n3498, n3499, n3500, n3501,
+ n3502, n3503, n3504, n3505, n3506, n3507, n3508, n3509, n3510, n3511,
+ n3512, n3513, n3514, n3515, n3516, n3517, n3518, n3519, n3520, n3521,
+ n3522, n3523, n3524, n3525, n3526, n3527, n3528, n3529, n3530, n3531,
+ n3532, n3533, n3534, n3535, n3536, n3537, n3538, n3539, n3540, n3541,
+ n3542, n3543, n3544, n3545, n3546, n3547, n3548, n3549, n3550, n3551,
+ n3552, n3553, n3554, n3555, n3556, n3557, n3558, n3559, n3560, n3561,
+ n3562, n3563, n3564, n3565, n3566, n3567, n3568, n3569, n3570, n3571,
+ n3572, n3573, n3574, n3575, n3576, n3577, n3578, n3579, n3580, n3581,
+ n3582, n3583, n3584, n3585, n3586, n3587, n3588, n3589, n3590, n3591,
+ n3592, n3593, n3594, n3595, n3596, n3597, n3598, n3599, n3600, n3601,
+ n3602, n3603, n3604, n3605, n3606, n3607, n3608, n3609, n3610, n3611,
+ n3612, n3613, n3614, n3615, n3616, n3617, n3618, n3619, n3620, n3621,
+ n3622, n3623, n3624, n3625, n3626, n3627, n3628, n3629, n3630, n3631,
+ n3632, n3633, n3634, n3635, n3636, n3637, n3638, n3639, n3640, n3641,
+ n3642, n3643, n3644, n3645, n3646, n3647, n3648, n3649, n3650, n3651,
+ n3652, n3653, n3654, n3655, n3656, n3657, n3658, n3659, n3660, n3661,
+ n3662, n3663, n3664, n3665, n3666, n3667, n3668, n3669, n3670, n3671,
+ n3672, n3673, n3674, n3675, n3676, n3677, n3678, n3679, n3680, n3681,
+ n3682, n3683, n3684, n3685, n3686, n3687, n3688, n3689, n3690, n3691,
+ n3692, n3693, n3694, n3695, n3696, n3697, n3698, n3699, n3700, n3701,
+ n3702, n3703, n3704, n3705, n3706, n3707, n3708, n3709, n3710, n3711,
+ n3712, n3713, n3714, n3715, n3716, n3717, n3718, n3719, n3720, n3721,
+ n3722, n3723, n3724, n3725, n3726, n3727, n3728, n3729, n3730, n3731,
+ n3732, n3733, n3734, n3735, n3736, n3737, n3738, n3739, n3740, n3741,
+ n3742, n3743, n3744, n3745, n3746, n3747, n3748, n3749, n3750, n3751,
+ n3752, n3753, n3754, n3755, n3756, n3757, n3758, n3759, n3760, n3761,
+ n3762, n3763, n3764, n3765, n3766, n3767, n3768, n3769, n3770, n3771,
+ n3772, n3773, n3774, n3775, n3776, n3777, n3778, n3779, n3780, n3781,
+ n3782, n3783, n3784, n3785, n3786, n3787, n3788, n3789, n3790, n3791,
+ n3792, n3793, n3794, n3795, n3796, n3797, n3798, n3799, n3800, n3801,
+ n3802, n3803, n3804, n3805, n3806, n3807, n3808, n3809, n3810, n3811,
+ n3812, n3813, n3814, n3815, n3816, n3817, n3818, n3819, n3820, n3821,
+ n3822, n3823, n3824, n3825, n3826, n3827, n3828, n3829, n3830, n3831,
+ n3832, n3833, n3834, n3835, n3836, n3837, n3838, n3839, n3840, n3841,
+ n3842, n3843, n3844, n3845, n3846, n3847, n3848, n3849, n3850, n3851,
+ n3852, n3853, n3854, n3855, n3856, n3857, n3858, n3859, n3860, n3861,
+ n3862, n3863, n3864, n3865, n3866, n3867, n3868, n3869, n3870, n3871,
+ n3872, n3873, n3874, n3875, n3876, n3877, n3878, n3879, n3880, n3881,
+ n3882, n3883, n3884, n3885, n3886, n3887, n3888, n3889, n3890, n3891,
+ n3892, n3893, n3894, n3895, n3896, n3897, n3898, n3899, n3900, n3901,
+ n3902, n3903, n3904, n3905, n3906, n3907, n3908, n3909, n3910, n3911,
+ n3912, n3913, n3914, n3915, n3916, n3917, n3918, n3919, n3920, n3921,
+ n3922, n3923, n3924, n3925, n3926, n3927, n3928, n3929, n3930, n3931,
+ n3932, n3933, n3934, n3935, n3936, n3937, n3938, n3939, n3940, n3941,
+ n3942, n3943, n3944, n3945, n3946, n3947, n3948, n3949, n3950, n3951,
+ n3952, n3953, n3954, n3955, n3956, n3957, n3958, n3959, n3960, n3961,
+ n3962, n3963, n3964, n3965, n3966, n3967, n3968, n3969, n3970, n3971,
+ n3972, n3973, n3974, n3975, n3976, n3977, n3978, n3979, n3980, n3981,
+ n3982, n3983, n3984, n3985, n3986, n3987, n3988, n3989, n3990, n3991,
+ n3992, n3993, n3994, n3995, n3996, n3997, n3998, n3999, n4000, n4001,
+ n4002, n4003, n4004, n4005, n4006, n4007, n4008, n4009, n4010, n4011,
+ n4012, n4013, n4014, n4015, n4016, n4017, n4018, n4019, n4020, n4021,
+ n4022, n4023, n4024, n4025, n4026, n4027, n4028, n4029, n4030, n4031,
+ n4032, n4033, n4034, n4035, n4036, n4037, n4038, n4039, n4040, n4041,
+ n4042, n4043, n4044, n4045, n4046, n4047, n4048, n4049, n4050, n4051,
+ n4052, n4053, n4054, n4055, n4056, n4057, n4058, n4059, n4060, n4061,
+ n4062, n4063, n4064, n4065, n4066, n4067, n4068, n4069, n4070, n4071,
+ n4072, n4073, n4074, n4075, n4076, n4077, n4078, n4079, n4080, n4081,
+ n4082, n4083, n4084, n4085, n4086, n4087, n4088, n4089, n4090, n4091,
+ n4092, n4093, n4094, n4095, n4096, n4097, n4098, n4099, n4100, n4101,
+ n4102, n4103, n4104, n4105, n4106, n4107, n4108, n4109, n4110, n4111,
+ n4112, n4113, n4114, n4115, n4116, n4117, n4118, n4119, n4120, n4121,
+ n4122, n4123, n4124, n4125, n4126, n4127, n4128, n4129, n4130, n4131,
+ n4132, n4133, n4134, n4135, n4136, n4137, n4138, n4139, n4140, n4141,
+ n4142, n4143, n4144, n4145, n4146, n4147, n4148, n4149, n4150, n4151,
+ n4152, n4153, n4154, n4155, n4156, n4157, n4158, n4159, n4160, n4161,
+ n4162, n4163, n4164, n4165, n4166, n4167, n4168, n4169, n4170, n4171,
+ n4172, n4173, n4174, n4175, n4176, n4177, n4178, n4179, n4180, n4181,
+ n4182, n4183, n4184, n4185, n4186, n4187, n4188, n4189, n4190, n4191,
+ n4192, n4193, n4194, n4195, n4196, n4197, n4198, n4199, n4200, n4201,
+ n4202, n4203, n4204, n4205, n4206, n4207, n4208, n4209, n4210, n4211,
+ n4212, n4213, n4214, n4215, n4216, n4217, n4218, n4219, n4220, n4221,
+ n4222, n4223, n4224, n4225, n4226, n4227, n4228, n4229, n4230, n4231,
+ n4232, n4233, n4234, n4235, n4236, n4237, n4238, n4239, n4240, n4241,
+ n4242, n4243, n4244, n4245, n4246, n4247, n4248, n4249, n4250, n4251,
+ n4252, n4253, n4254, n4255, n4256, n4257, n4258, n4259, n4260, n4261,
+ n4262, n4263, n4264, n4265, n4266, n4267, n4268, n4269, n4270, n4271,
+ n4272, n4273, n4274, n4275, n4276, n4277, n4278, n4279, n4280, n4281,
+ n4282, n4283, n4284, n4285, n4286, n4287, n4288, n4289, n4290, n4291,
+ n4292, n4293, n4294, n4295, n4296, n4297, n4298, n4299, n4300, n4301,
+ n4302, n4303, n4304, n4305, n4306, n4307, n4308, n4309, n4310, n4311,
+ n4312, n4313, n4314, n4315, n4316, n4317, n4318, n4319, n4320, n4321,
+ n4322, n4323, n4324, n4325, n4326, n4327, n4328, n4329, n4330, n4331,
+ n4332, n4333, n4334, n4335, n4336, n4337, n4338, n4339, n4340, n4341,
+ n4342, n4343, n4344, n4345, n4346, n4347, n4348, n4349, n4350, n4351,
+ n4352, n4353, n4354, n4355, n4356, n4357, n4358, n4359, n4360, n4361,
+ n4362, n4363, n4364, n4365, n4366, n4367, n4368, n4369, n4370, n4371,
+ n4372, n4373, n4374, n4375, n4376, n4377, n4378, n4379, n4380, n4381,
+ n4382, n4383, n4384, n4385, n4386, n4387, n4388, n4389, n4390, n4391,
+ n4392, n4393, n4394, n4395, n4396, n4397, n4398, n4399, n4400, n4401,
+ n4402, n4403, n4404, n4405, n4406, n4407, n4408, n4409, n4410, n4411,
+ n4412, n4413, n4414, n4415, n4416, n4417, n4418, n4419, n4420, n4421,
+ n4422, n4423, n4424, n4425, n4426, n4427, n4428, n4429, n4430, n4431,
+ n4432, n4433, n4434, n4435, n4436, n4437, n4438, n4439, n4440, n4441,
+ n4442, n4443, n4444, n4445, n4446, n4447, n4448, n4449, n4450, n4451,
+ n4452, n4453, n4454, n4455, n4456, n4457, n4458, n4459, n4460, n4461,
+ n4462, n4463, n4464, n4465, n4466, n4467, n4468, n4469, n4470, n4471,
+ n4472, n4473, n4474, n4475, n4476, n4477, n4478, n4479, n4480, n4481,
+ n4482, n4483, n4484, n4485, n4486, n4487, n4488, n4489, n4490, n4491,
+ n4492, n4493, n4494, n4495, n4496, n4497, n4498, n4499, n4500, n4501,
+ n4502, n4503, n4504, n4505, n4506, n4507, n4508, n4509, n4510, n4511,
+ n4512, n4513, n4514, n4515, n4516, n4517, n4518, n4519, n4520, n4521,
+ n4522, n4523, n4524, n4525, n4526, n4527, n4528, n4529, n4530, n4531,
+ n4532, n4533, n4534, n4535, n4536, n4537, n4538, n4539, n4540, n4541,
+ n4542, n4543, n4544, n4545, n4546, n4547, n4548, n4549, n4550, n4551,
+ n4552, n4553, n4554, n4555, n4556, n4557, n4558, n4559, n4560, n4561,
+ n4562, n4563, n4564, n4565, n4566, n4567, n4568, n4569, n4570, n4571,
+ n4572, n4573, n4574, n4575, n4576, n4577, n4578, n4579, n4580, n4581,
+ n4582, n4583, n4584, n4585, n4586, n4587, n4588, n4589, n4590, n4591,
+ n4592, n4593, n4594, n4595, n4596, n4597, n4598, n4599, n4600, n4601,
+ n4602, n4603, n4604, n4605, n4606, n4607, n4608, n4609, n4610, n4611,
+ n4612, n4613, n4614, n4615, n4616, n4617, n4618, n4619, n4620, n4621,
+ n4622, n4623, n4624, n4625, n4626, n4627, n4628, n4629, n4630, n4631,
+ n4632, n4633, n4634, n4635, n4636, n4637, n4638, n4639, n4640, n4641,
+ n4642, n4643, n4644, n4645, n4646, n4647, n4648, n4649, n4650, n4651,
+ n4652, n4653, n4654, n4655, n4656, n4657, n4658, n4659, n4660, n4661,
+ n4662, n4663, n4664, n4665, n4666, n4667, n4668, n4669, n4670, n4671,
+ n4672, n4673, n4674, n4675, n4676, n4677, n4678, n4679, n4680, n4681,
+ n4682, n4683, n4684, n4685, n4686, n4687, n4688, n4689, n4690, n4691,
+ n4692, n4693, n4694, n4695, n4696, n4697, n4698, n4699, n4700, n4701,
+ n4702, n4703, n4704, n4705, n4706, n4707, n4708, n4709, n4710, n4711,
+ n4712, n4713, n4714, n4715, n4716, n4717, n4718, n4719, n4720, n4721,
+ n4722, n4723, n4724, n4725, n4726, n4727, n4728, n4729, n4730, n4731,
+ n4732, n4733, n4734, n4735, n4736, n4737, n4738, n4739, n4740, n4741,
+ n4742, n4743, n4744, n4745, n4746, n4747, n4748, n4749, n4750, n4751,
+ n4752, n4753, n4754, n4755, n4756, n4757, n4758, n4759, n4760, n4761,
+ n4762, n4763, n4764, n4765, n4766, n4767, n4768, n4769, n4770, n4771,
+ n4772, n4773, n4774, n4775, n4776, n4777, n4778, n4779, n4780, n4781,
+ n4782, n4783, n4784, n4785, n4786, n4787, n4788, n4789, n4790, n4791,
+ n4792, n4793, n4794, n4795, n4796, n4797, n4798, n4799, n4800, n4801,
+ n4802, n4803, n4804, n4805, n4806, n4807, n4808, n4809, n4810, n4811,
+ n4812, n4813, n4814, n4815, n4816, n4817, n4818, n4819, n4820, n4821,
+ n4822, n4823, n4824, n4825, n4826, n4827, n4828, n4829, n4830, n4831,
+ n4832, n4833, n4834, n4835, n4836, n4837, n4838, n4839, n4840, n4841,
+ n4842, n4843, n4844, n4845, n4846, n4847, n4848, n4849, n4850, n4851,
+ n4852, n4853, n4854, n4855, n4856, n4857, n4858, n4859, n4860, n4861,
+ n4862, n4863, n4864, n4865, n4866, n4867, n4868, n4869, n4870, n4871,
+ n4872, n4873, n4874, n4875, n4876, n4877, n4878, n4879, n4880, n4881,
+ n4882, n4883, n4884, n4885, n4886, n4887, n4888, n4889, n4890, n4891,
+ n4892, n4893, n4894, n4895, n4896, n4897, n4898, n4899, n4900, n4901,
+ n4902, n4903, n4904, n4905, n4906, n4907, n4908, n4909, n4910, n4911,
+ n4912, n4913, n4914, n4915, n4916, n4917, n4918, n4919, n4920, n4921,
+ n4922, n4923, n4924, n4925, n4926, n4927, n4928, n4929, n4930, n4931,
+ n4932, n4933, n4934, n4935, n4936, n4937, n4938, n4939, n4940, n4941,
+ n4942, n4943, n4944, n4945, n4946, n4947, n4948, n4949, n4950, n4951,
+ n4952, n4953, n4954, n4955, n4956, n4957, n4958, n4959, n4960, n4961,
+ n4962, n4963, n4964, n4965, n4966, n4967, n4968, n4969, n4970, n4971,
+ n4972, n4973, n4974, n4975, n4976, n4977, n4978, n4979, n4980, n4981,
+ n4982, n4983, n4984, n4985, n4986, n4987, n4988, n4989, n4990, n4991,
+ n4992, n4993, n4994, n4995, n4996, n4997, n4998, n4999, n5000, n5001,
+ n5002, n5003, n5004, n5005, n5006, n5007, n5008, n5009, n5010, n5011,
+ n5012, n5013, n5014, n5015, n5016, n5017, n5018, n5019, n5020, n5021,
+ n5022, n5023, n5024, n5025, n5026, n5027, n5028, n5029, n5030, n5031,
+ n5032, n5033, n5034, n5035, n5036, n5037, n5038, n5039, n5040, n5041,
+ n5042, n5043, n5044, n5045, n5046, n5047, n5048, n5049, n5050, n5051,
+ n5052, n5053, n5054, n5055, n5056, n5057, n5058, n5059, n5060, n5061,
+ n5062, n5063, n5064, n5065, n5066, n5067, n5068, n5069, n5070, n5071,
+ n5072, n5073, n5074, n5075, n5076, n5077, n5078, n5079, n5080, n5081,
+ n5082, n5083, n5084, n5085, n5086, n5087, n5088, n5089, n5090, n5091,
+ n5092, n5093, n5094, n5095, n5096, n5097, n5098, n5099, n5100, n5101,
+ n5102, n5103, n5104, n5105, n5106, n5107, n5108, n5109, n5110, n5111,
+ n5112, n5113, n5114, n5115, n5116, n5117, n5118, n5119, n5120, n5121,
+ n5122, n5123, n5124, n5125, n5126, n5127, n5128, n5129, n5130, n5131,
+ n5132, n5133, n5134, n5135, n5136, n5137, n5138, n5139, n5140, n5141,
+ n5142, n5143, n5144, n5145, n5146, n5147, n5148, n5149, n5150, n5151,
+ n5152, n5153, n5154, n5155, n5156, n5157, n5158, n5159, n5160, n5161,
+ n5162, n5163, n5164, n5165, n5166, n5167, n5168, n5169, n5170, n5171,
+ n5172, n5173, n5174, n5175, n5176, n5177, n5178, n5179, n5180, n5181,
+ n5182, n5183, n5184, n5185, n5186, n5187, n5188, n5189, n5190, n5191,
+ n5192, n5193, n5194, n5195, n5196, n5197, n5198, n5199, n5200, n5201,
+ n5202, n5203, n5204, n5205, n5206, n5207, n5208, n5209, n5210, n5211,
+ n5212, n5213, n5214, n5215, n5216, n5217, n5218, n5219, n5220, n5221,
+ n5222, n5223, n5224, n5225, n5226, n5227, n5228, n5229, n5230, n5231,
+ n5232, n5233, n5234, n5235, n5236, n5237, n5238, n5239, n5240, n5241,
+ n5242, n5243, n5244, n5245, n5246, n5247, n5248, n5249, n5250, n5251,
+ n5252, n5253, n5254, n5255, n5256, n5257, n5258, n5259, n5260, n5261,
+ n5262, n5263, n5264, n5265, n5266, n5267, n5268, n5269, n5270, n5271,
+ n5272, n5273, n5274, n5275, n5276, n5277, n5278, n5279, n5280, n5281,
+ n5282, n5283, n5284, n5285, n5286, n5287, n5288, n5289, n5290, n5291,
+ n5292, n5293, n5294, n5295, n5296, n5297, n5298, n5299, n5300, n5301,
+ n5302, n5303, n5304, n5305, n5306, n5307, n5308, n5309, n5310, n5311,
+ n5312, n5313, n5314, n5315, n5316, n5317, n5318, n5319, n5320, n5321,
+ n5322, n5323, n5324, n5325, n5326, n5327, n5328, n5329, n5330, n5331,
+ n5332, n5333, n5334, n5335, n5336, n5337, n5338, n5339, n5340, n5341,
+ n5342, n5343, n5344, n5345, n5346, n5347, n5348, n5349, n5350, n5351,
+ n5352, n5353, n5354, n5355, n5356, n5357, n5358, n5359, n5360, n5361,
+ n5362, n5363, n5364, n5365, n5366, n5367, n5368, n5369, n5370, n5371,
+ n5372, n5373, n5374, n5375, n5376, n5377, n5378, n5379, n5380, n5381,
+ n5382, n5383, n5384, n5385, n5386, n5387, n5388, n5389, n5390, n5391,
+ n5392, n5393, n5394, n5395, n5396, n5397, n5398, n5399, n5400, n5401,
+ n5402, n5403, n5404, n5405, n5406, n5407, n5408, n5409, n5410, n5411,
+ n5412, n5413, n5414, n5415, n5416, n5417, n5418, n5419, n5420, n5421,
+ n5422, n5423, n5424, n5425, n5426, n5427, n5428, n5429, n5430, n5431,
+ n5432, n5433, n5434, n5435, n5436, n5437, n5438, n5439, n5440, n5441,
+ n5442, n5443, n5444, n5445, n5446, n5447, n5448, n5449, n5450, n5451,
+ n5452, n5453, n5454, n5455, n5456, n5457, n5458, n5459, n5460, n5461,
+ n5462, n5463, n5464, n5465, n5466, n5467, n5468, n5469, n5470, n5471,
+ n5472, n5473, n5474, n5475, n5476, n5477, n5478, n5479, n5480, n5481,
+ n5482, n5483, n5484, n5485, n5486, n5487, n5488, n5489, n5490, n5491,
+ n5492, n5493, n5494, n5495, n5496, n5497, n5498, n5499, n5500, n5501,
+ n5502, n5503, n5504, n5505, n5506, n5507, n5508, n5509, n5510, n5511,
+ n5512, n5513, n5514, n5515, n5516, n5517, n5518, n5519, n5520, n5521,
+ n5522, n5523, n5524, n5525, n5526, n5527, n5528, n5529, n5530, n5531,
+ n5532, n5533, n5534, n5535, n5536, n5537, n5538, n5539, n5540, n5541,
+ n5542, n5543, n5544, n5545, n5546, n5547, n5548, n5549, n5550, n5551,
+ n5552, n5553, n5554, n5555, n5556, n5557, n5558, n5559, n5560, n5561,
+ n5562, n5563, n5564, n5565, n5566, n5567, n5568, n5569, n5570, n5571,
+ n5572, n5573, n5574, n5575, n5576, n5577, n5578, n5579, n5580, n5581,
+ n5582, n5583, n5584, n5585, n5586, n5587, n5588, n5589, n5590, n5591,
+ n5592, n5593, n5594, n5595, n5596, n5597, n5598, n5599, n5600, n5601,
+ n5602, n5603, n5604, n5605, n5606, n5607, n5608, n5609, n5610, n5611,
+ n5612, n5613, n5614, n5615, n5616, n5617, n5618, n5619, n5620, n5621,
+ n5622, n5623, n5624, n5625, n5626, n5627, n5628, n5629, n5630, n5631,
+ n5632, n5633, n5634, n5635, n5636, n5637, n5638, n5639, n5640, n5641,
+ n5642, n5643, n5644, n5645, n5646, n5647, n5648, n5649, n5650, n5651,
+ n5652, n5653, n5654, n5655, n5656, n5657, n5658, n5659, n5660, n5661,
+ n5662, n5663, n5664, n5665, n5666, n5667, n5668, n5669, n5670, n5671,
+ n5672, n5673, n5674, n5675, n5676, n5677, n5678, n5679, n5680, n5681,
+ n5682, n5683, n5684, n5685, n5686, n5687, n5688, n5689, n5690, n5691,
+ n5692, n5693, n5694, n5695, n5696, n5697, n5698, n5699, n5700, n5701,
+ n5702, n5703, n5704, n5705, n5706, n5707, n5708, n5709, n5710, n5711,
+ n5712, n5713, n5714, n5715, n5716, n5717, n5718, n5719, n5720, n5721,
+ n5722, n5723, n5724, n5725, n5726, n5727, n5728, n5729, n5730, n5731,
+ n5732, n5733, n5734, n5735, n5736, n5737, n5738, n5739, n5740, n5741,
+ n5742, n5743, n5744, n5745, n5746, n5747, n5748, n5749, n5750, n5751,
+ n5752, n5753, n5754, n5755, n5756, n5757, n5758, n5759, n5760, n5761,
+ n5762, n5763, n5764, n5765, n5766, n5767, n5768, n5769, n5770, n5771,
+ n5772, n5773, n5774, n5775, n5776, n5777, n5778, n5779, n5780, n5781,
+ n5782, n5783, n5784, n5785, n5786, n5787, n5788, n5789, n5790, n5791,
+ n5792, n5793, n5794, n5795, n5796, n5797, n5798, n5799, n5800, n5801,
+ n5802, n5803, n5804, n5805, n5806, n5807, n5808, n5809, n5810, n5811,
+ n5812, n5813, n5814, n5815, n5816, n5817, n5818, n5819, n5820, n5821,
+ n5822, n5823, n5824, n5825, n5826, n5827, n5828, n5829, n5830, n5831,
+ n5832, n5833, n5834, n5835, n5836, n5837, n5838, n5839, n5840, n5841,
+ n5842, n5843, n5844, n5845, n5846, n5847, n5848, n5849, n5850, n5851,
+ n5852, n5853, n5854, n5855, n5856, n5857, n5858, n5859, n5860, n5861,
+ n5862, n5863, n5864, n5865, n5866, n5867, n5868, n5869, n5870, n5871,
+ n5872, n5873, n5874, n5875, n5876, n5877, n5878, n5879, n5880, n5881,
+ n5882, n5883, n5884, n5885, n5886, n5887, n5888, n5889, n5890, n5891,
+ n5892, n5893, n5894, n5895, n5896, n5897, n5898, n5899, n5900, n5901,
+ n5902, n5903, n5904, n5905, n5906, n5907, n5908, n5909, n5910, n5911,
+ n5912, n5913, n5914, n5915, n5916, n5917, n5918, n5919, n5920, n5921,
+ n5922, n5923, n5924, n5925, n5926, n5927, n5928, n5929, n5930, n5931,
+ n5932, n5933, n5934, n5935, n5936, n5937, n5938, n5939, n5940, n5941,
+ n5942, n5943, n5944, n5945, n5946, n5947, n5948, n5949, n5950, n5951,
+ n5952, n5953, n5954, n5955, n5956, n5957, n5958, n5959, n5960, n5961,
+ n5962, n5963, n5964, n5965, n5966, n5967, n5968, n5969, n5970, n5971,
+ n5972, n5973, n5974, n5975, n5976, n5977, n5978, n5979, n5980, n5981,
+ n5982, n5983, n5984, n5985, n5986, n5987, n5988, n5989, n5990, n5991,
+ n5992, n5993, n5994, n5995, n5996, n5997, n5998, n5999, n6000, n6001,
+ n6002, n6003, n6004, n6005, n6006, n6007, n6008, n6009, n6010, n6011,
+ n6012, n6013, n6014, n6015, n6016, n6017, n6018, n6019, n6020, n6021,
+ n6022, n6023, n6024, n6025, n6026, n6027, n6028, n6029, n6030, n6031,
+ n6032, n6033, n6034, n6035, n6036, n6037, n6038, n6039, n6040, n6041,
+ n6042, n6043, n6044, n6045, n6046, n6047, n6048, n6049, n6050, n6051,
+ n6052, n6053, n6054, n6055, n6056, n6057, n6058, n6059, n6060, n6061,
+ n6062, n6063, n6064, n6065, n6066, n6067, n6068, n6069, n6070, n6071,
+ n6072, n6073, n6074, n6075, n6076, n6077, n6078, n6079, n6080, n6081,
+ n6082, n6083, n6084, n6085, n6086, n6087, n6088, n6089, n6090, n6091,
+ n6092, n6093, n6094, n6095, n6096, n6097, n6098, n6099, n6100, n6101,
+ n6102, n6103, n6104, n6105, n6106, n6107, n6108, n6109, n6110, n6111,
+ n6112, n6113, n6114, n6115, n6116, n6117, n6118, n6119, n6120, n6121,
+ n6122, n6123, n6124, n6125, n6126, n6127, n6128, n6129, n6130, n6131,
+ n6132, n6133, n6134, n6135, n6136, n6137, n6138, n6139, n6140, n6141,
+ n6142, n6143, n6144, n6145, n6146, n6147, n6148, n6149, n6150, n6151,
+ n6152, n6153, n6154, n6155, n6156, n6157, n6158, n6159, n6160, n6161,
+ n6162, n6163, n6164, n6165, n6166, n6167, n6168, n6169, n6170, n6171,
+ n6172, n6173, n6174, n6175, n6176, n6177, n6178, n6179, n6180, n6181,
+ n6182, n6183, n6184, n6185, n6186, n6187, n6188, n6189, n6190, n6191,
+ n6192, n6193, n6194, n6195, n6196, n6197, n6198, n6199, n6200, n6201,
+ n6202, n6203, n6204, n6205, n6206, n6207, n6208, n6209, n6210, n6211,
+ n6212, n6213, n6214, n6215, n6216, n6217, n6218, n6219, n6220, n6221,
+ n6222, n6223, n6224, n6225, n6226, n6227, n6228, n6229, n6230, n6231,
+ n6232, n6233, n6234, n6235, n6236, n6237, n6238, n6239, n6240, n6241,
+ n6242, n6243, n6244, n6245, n6246, n6247, n6248, n6249, n6250, n6251,
+ n6252, n6253, n6254, n6255, n6256, n6257, n6258, n6259, n6260, n6261,
+ n6262, n6263, n6264, n6265, n6266, n6267, n6268, n6269, n6270, n6271,
+ n6272, n6273, n6274, n6275, n6276, n6277, n6278, n6279, n6280, n6281,
+ n6282, n6283, n6284, n6285, n6286, n6287, n6288, n6289, n6290, n6291,
+ n6292, n6293, n6294, n6295, n6296, n6297, n6298, n6299, n6300, n6301,
+ n6302, n6303, n6304, n6305, n6306, n6307, n6308, n6309, n6310, n6311,
+ n6312, n6313, n6314, n6315, n6316, n6317, n6318, n6319, n6320, n6321,
+ n6322, n6323, n6324, n6325, n6326, n6327, n6328, n6329, n6330, n6331,
+ n6332, n6333, n6334, n6335, n6336, n6337, n6338, n6339, n6340, n6341,
+ n6342, n6343, n6344, n6345, n6346, n6347, n6348, n6349, n6350, n6351,
+ n6352, n6353, n6354, n6355, n6356, n6357, n6358, n6359, n6360, n6361,
+ n6362, n6363, n6364, n6365, n6366, n6367, n6368, n6369, n6370, n6371,
+ n6372, n6373, n6374, n6375, n6376, n6377, n6378, n6379, n6380, n6381,
+ n6382, n6383, n6384, n6385, n6386, n6387, n6388, n6389, n6390, n6391,
+ n6392, n6393, n6394, n6395, n6396, n6397, n6398, n6399, n6400, n6401,
+ n6402, n6403, n6404, n6405;
+
+assign po001 = pi187;
+
+assign po015 = po003;
+
+assign po004 = pi106;
+
+assign po009 = pi136;
+
+assign po010 = pi022;
+
+assign po011 = pi112;
+
+assign po005 = po012;
+
+assign po013 = pi062;
+
+assign po014 = pi123;
+
+assign po101 = po023;
+
+assign po067 = po023;
+
+assign po066 = po023;
+
+assign po023 = pi119;
+
+assign po024 = pi152;
+
+assign po025 = pi125;
+
+assign po027 = pi102;
+
+assign po028 = pi031;
+
+assign po031 = pi155;
+
+assign po065 = po034;
+
+assign po035 = pi182;
+
+assign po036 = pi023;
+
+assign po038 = pi071;
+
+assign po039 = pi015;
+
+assign po040 = pi132;
+
+assign po044 = pi044;
+
+assign po052 = pi048;
+
+assign po057 = pi117;
+
+assign po059 = pi091;
+
+assign po063 = pi000;
+
+assign po064 = pi194;
+
+assign po069 = pi147;
+
+assign po070 = pi002;
+
+assign po071 = pi080;
+
+assign po072 = pi188;
+
+assign po018 = po074;
+
+assign po021 = po074;
+
+assign po079 = pi084;
+
+assign po082 = pi144;
+
+assign po084 = pi199;
+
+assign po085 = pi066;
+
+assign po091 = pi008;
+
+assign po092 = pi154;
+
+assign po099 = pi042;
+
+assign po102 = pi179;
+
+assign po103 = pi145;
+
+assign po104 = pi127;
+
+assign po106 = pi105;
+
+assign po107 = pi029;
+
+assign po020 = po041;
+
+assign po032 = po007;
+
+assign po089 = po076;
+
+assign po054 = po076;
+
+ OR2 U2865 ( .A(n2822), .B(n2823), .Z(po100));
+ AN2 U2866 ( .A(n2824), .B(pi192), .Z(n2823));
+ OR2 U2867 ( .A(n2825), .B(n2826), .Z(n2824));
+ AN2 U2868 ( .A(n2827), .B(n2828), .Z(n2826));
+ IV2 U2869 ( .A(n2829), .Z(n2825));
+ OR2 U2870 ( .A(n2828), .B(n2827), .Z(n2829));
+ OR2 U2871 ( .A(n2830), .B(n2831), .Z(n2827));
+ AN2 U2872 ( .A(n2832), .B(n2833), .Z(n2831));
+ AN2 U2873 ( .A(n2834), .B(n2835), .Z(n2830));
+ AN2 U2874 ( .A(n2836), .B(n2837), .Z(n2822));
+ OR2 U2875 ( .A(n2838), .B(n2839), .Z(n2836));
+ AN2 U2876 ( .A(n2840), .B(n2828), .Z(n2839));
+ IV2 U2877 ( .A(n2841), .Z(n2838));
+ OR2 U2878 ( .A(n2828), .B(n2840), .Z(n2841));
+ OR2 U2879 ( .A(n2842), .B(n2843), .Z(n2840));
+ AN2 U2880 ( .A(n2844), .B(n2845), .Z(n2843));
+ AN2 U2881 ( .A(n2846), .B(n2847), .Z(n2842));
+ AN2 U2882 ( .A(n2848), .B(n2849), .Z(n2828));
+ IV2 U2883 ( .A(n2850), .Z(n2849));
+ AN2 U2884 ( .A(n2851), .B(n2852), .Z(n2850));
+ OR2 U2885 ( .A(n2852), .B(n2851), .Z(n2848));
+ OR2 U2886 ( .A(n2853), .B(n2854), .Z(n2851));
+ AN2 U2887 ( .A(n2855), .B(n2856), .Z(n2854));
+ IV2 U2888 ( .A(n2857), .Z(n2853));
+ OR2 U2889 ( .A(n2856), .B(n2855), .Z(n2857));
+ IV2 U2890 ( .A(n2858), .Z(n2855));
+ OR2 U2891 ( .A(n2859), .B(n2860), .Z(n2858));
+ AN2 U2892 ( .A(n2861), .B(n2862), .Z(n2859));
+ OR2 U2893 ( .A(n2863), .B(n2864), .Z(n2856));
+ OR2 U2894 ( .A(n2865), .B(n2866), .Z(n2864));
+ AN2 U2895 ( .A(pi192), .B(n2867), .Z(n2866));
+ OR2 U2896 ( .A(n2868), .B(n2869), .Z(n2867));
+ OR2 U2897 ( .A(n2870), .B(n2871), .Z(n2869));
+ AN2 U2898 ( .A(n2872), .B(n2873), .Z(n2871));
+ AN2 U2899 ( .A(n2862), .B(n2874), .Z(n2872));
+ OR2 U2900 ( .A(n2875), .B(n2876), .Z(n2874));
+ AN2 U2901 ( .A(n2877), .B(n2878), .Z(n2875));
+ AN2 U2902 ( .A(n2879), .B(n2880), .Z(n2870));
+ AN2 U2903 ( .A(n2881), .B(n2882), .Z(n2868));
+ OR2 U2904 ( .A(n2883), .B(n2884), .Z(n2881));
+ AN2 U2905 ( .A(n2885), .B(n2886), .Z(n2884));
+ AN2 U2906 ( .A(n2879), .B(n2887), .Z(n2883));
+ IV2 U2907 ( .A(n2873), .Z(n2879));
+ OR2 U2908 ( .A(n2888), .B(n2889), .Z(n2873));
+ AN2 U2909 ( .A(n2890), .B(n2891), .Z(n2889));
+ AN2 U2910 ( .A(n2892), .B(n2886), .Z(n2888));
+ AN2 U2911 ( .A(n2893), .B(n2837), .Z(n2865));
+ OR2 U2912 ( .A(n2894), .B(n2895), .Z(n2893));
+ OR2 U2913 ( .A(n2896), .B(n2897), .Z(n2895));
+ OR2 U2914 ( .A(n2898), .B(n2899), .Z(n2897));
+ AN2 U2915 ( .A(n2900), .B(n2901), .Z(n2899));
+ AN2 U2916 ( .A(n2902), .B(n2903), .Z(n2900));
+ OR2 U2917 ( .A(n2904), .B(n2905), .Z(n2903));
+ OR2 U2918 ( .A(n2906), .B(n2907), .Z(n2905));
+ AN2 U2919 ( .A(n2890), .B(n2908), .Z(n2907));
+ AN2 U2920 ( .A(n2909), .B(n2886), .Z(n2906));
+ AN2 U2921 ( .A(n2910), .B(pi082), .Z(n2909));
+ AN2 U2922 ( .A(pi200), .B(n2911), .Z(n2898));
+ OR2 U2923 ( .A(n2912), .B(n2913), .Z(n2911));
+ OR2 U2924 ( .A(n2914), .B(n2915), .Z(n2913));
+ AN2 U2925 ( .A(n2916), .B(n2890), .Z(n2915));
+ AN2 U2926 ( .A(n2910), .B(n2917), .Z(n2916));
+ OR2 U2927 ( .A(n2918), .B(n2919), .Z(n2917));
+ AN2 U2928 ( .A(n2920), .B(n2886), .Z(n2914));
+ OR2 U2929 ( .A(n2921), .B(n2922), .Z(n2920));
+ OR2 U2930 ( .A(n2923), .B(n2924), .Z(n2922));
+ AN2 U2931 ( .A(n2918), .B(n2860), .Z(n2924));
+ AN2 U2932 ( .A(n2925), .B(n2926), .Z(n2923));
+ OR2 U2933 ( .A(n2927), .B(n2928), .Z(n2926));
+ AN2 U2934 ( .A(n2844), .B(n2929), .Z(n2928));
+ AN2 U2935 ( .A(n2930), .B(n2931), .Z(n2927));
+ OR2 U2936 ( .A(n2932), .B(n2933), .Z(n2921));
+ AN2 U2937 ( .A(n2934), .B(n2935), .Z(n2933));
+ AN2 U2938 ( .A(n2936), .B(n2910), .Z(n2934));
+ AN2 U2939 ( .A(n2937), .B(n2938), .Z(n2932));
+ AN2 U2940 ( .A(n2929), .B(n2939), .Z(n2937));
+ AN2 U2941 ( .A(n2935), .B(n2940), .Z(n2912));
+ OR2 U2942 ( .A(n2904), .B(n2941), .Z(n2940));
+ AN2 U2943 ( .A(n2890), .B(n2942), .Z(n2941));
+ AN2 U2944 ( .A(n2943), .B(n2944), .Z(n2942));
+ OR2 U2945 ( .A(n2945), .B(n2946), .Z(n2944));
+ IV2 U2946 ( .A(n2910), .Z(n2945));
+ OR2 U2947 ( .A(n2936), .B(n2947), .Z(n2943));
+ IV2 U2948 ( .A(n2948), .Z(n2904));
+ OR2 U2949 ( .A(n2949), .B(n2939), .Z(n2948));
+ AN2 U2950 ( .A(n2950), .B(n2951), .Z(n2949));
+ OR2 U2951 ( .A(n2890), .B(n2947), .Z(n2951));
+ OR2 U2952 ( .A(n2929), .B(n2886), .Z(n2950));
+ AN2 U2953 ( .A(n2952), .B(n2953), .Z(n2896));
+ AN2 U2954 ( .A(n2954), .B(n2955), .Z(n2953));
+ OR2 U2955 ( .A(n2956), .B(n2957), .Z(n2955));
+ AN2 U2956 ( .A(n2890), .B(n2958), .Z(n2956));
+ OR2 U2957 ( .A(n2959), .B(n2960), .Z(n2958));
+ OR2 U2958 ( .A(pi082), .B(n2961), .Z(n2954));
+ AN2 U2959 ( .A(n2901), .B(n2886), .Z(n2961));
+ AN2 U2960 ( .A(n2910), .B(n2962), .Z(n2952));
+ AN2 U2961 ( .A(n2947), .B(n2862), .Z(n2910));
+ OR2 U2962 ( .A(n2963), .B(n2964), .Z(n2894));
+ AN2 U2963 ( .A(n2965), .B(n2890), .Z(n2964));
+ AN2 U2964 ( .A(n2929), .B(n2966), .Z(n2965));
+ OR2 U2965 ( .A(n2967), .B(n2968), .Z(n2966));
+ AN2 U2966 ( .A(n2969), .B(n2901), .Z(n2967));
+ OR2 U2967 ( .A(n2970), .B(n2971), .Z(n2969));
+ OR2 U2968 ( .A(n2972), .B(n2973), .Z(n2971));
+ AN2 U2969 ( .A(n2902), .B(n2962), .Z(n2973));
+ AN2 U2970 ( .A(n2974), .B(n2957), .Z(n2972));
+ AN2 U2971 ( .A(pi082), .B(po031), .Z(n2970));
+ AN2 U2972 ( .A(n2975), .B(n2886), .Z(n2963));
+ OR2 U2973 ( .A(n2976), .B(n2977), .Z(n2975));
+ AN2 U2974 ( .A(n2968), .B(n2947), .Z(n2977));
+ AN2 U2975 ( .A(n2978), .B(n2979), .Z(n2968));
+ OR2 U2976 ( .A(n2980), .B(n2981), .Z(n2979));
+ AN2 U2977 ( .A(n2982), .B(n2931), .Z(n2980));
+ AN2 U2978 ( .A(n2983), .B(n2929), .Z(n2976));
+ AN2 U2979 ( .A(n2984), .B(n2936), .Z(n2983));
+ AN2 U2980 ( .A(n2974), .B(n2901), .Z(n2984));
+ OR2 U2981 ( .A(n2985), .B(n2986), .Z(n2863));
+ AN2 U2982 ( .A(n2987), .B(n2890), .Z(n2986));
+ AN2 U2983 ( .A(n2988), .B(n2989), .Z(n2987));
+ AN2 U2984 ( .A(n2990), .B(n2962), .Z(n2989));
+ AN2 U2985 ( .A(n2862), .B(n2877), .Z(n2988));
+ AN2 U2986 ( .A(n2991), .B(n2886), .Z(n2985));
+ OR2 U2987 ( .A(n2992), .B(n2993), .Z(n2991));
+ AN2 U2988 ( .A(n2994), .B(n2995), .Z(n2993));
+ AN2 U2989 ( .A(n2990), .B(n2901), .Z(n2995));
+ AN2 U2990 ( .A(n2996), .B(n2974), .Z(n2994));
+ OR2 U2991 ( .A(po031), .B(n2930), .Z(n2996));
+ AN2 U2992 ( .A(n2997), .B(n2860), .Z(n2992));
+ AN2 U2993 ( .A(n2998), .B(n2930), .Z(n2860));
+ AN2 U2994 ( .A(n2877), .B(n2999), .Z(n2997));
+ IV2 U2995 ( .A(n2882), .Z(n2877));
+ AN2 U2996 ( .A(n3000), .B(n3001), .Z(n2852));
+ OR2 U2997 ( .A(n3002), .B(n2925), .Z(n3001));
+ OR2 U2998 ( .A(n3003), .B(n3004), .Z(n3000));
+ IV2 U2999 ( .A(n3002), .Z(n3004));
+ OR2 U3000 ( .A(n3005), .B(n3006), .Z(n3002));
+ AN2 U3001 ( .A(n3007), .B(n3008), .Z(n3006));
+ OR2 U3002 ( .A(n3009), .B(n3010), .Z(n3008));
+ AN2 U3003 ( .A(n3011), .B(n3012), .Z(n3009));
+ AN2 U3004 ( .A(n3013), .B(n3014), .Z(n3007));
+ OR2 U3005 ( .A(n3015), .B(n3016), .Z(n3014));
+ IV2 U3006 ( .A(n3017), .Z(n3016));
+ OR2 U3007 ( .A(n3017), .B(n3018), .Z(n3013));
+ OR2 U3008 ( .A(n3019), .B(n3020), .Z(n3017));
+ AN2 U3009 ( .A(n3021), .B(n3022), .Z(n3020));
+ OR2 U3010 ( .A(n3023), .B(n3024), .Z(n3022));
+ OR2 U3011 ( .A(n3025), .B(n3026), .Z(n3024));
+ OR2 U3012 ( .A(n3027), .B(n3028), .Z(n3026));
+ AN2 U3013 ( .A(po010), .B(n3029), .Z(n3028));
+ AN2 U3014 ( .A(n3030), .B(pi192), .Z(n3027));
+ AN2 U3015 ( .A(n3031), .B(n3032), .Z(n3030));
+ OR2 U3016 ( .A(n3033), .B(n3034), .Z(n3032));
+ AN2 U3017 ( .A(n3035), .B(n3036), .Z(n3034));
+ AN2 U3018 ( .A(n3015), .B(n3037), .Z(n3035));
+ OR2 U3019 ( .A(n3038), .B(n3039), .Z(n3031));
+ OR2 U3020 ( .A(n3040), .B(n3041), .Z(n3039));
+ AN2 U3021 ( .A(po010), .B(n3042), .Z(n3040));
+ OR2 U3022 ( .A(n3043), .B(n3044), .Z(n3025));
+ AN2 U3023 ( .A(n3015), .B(n3045), .Z(n3044));
+ OR2 U3024 ( .A(n3046), .B(n3047), .Z(n3045));
+ AN2 U3025 ( .A(n3048), .B(n3049), .Z(n3047));
+ OR2 U3026 ( .A(n3050), .B(n3051), .Z(n3048));
+ AN2 U3027 ( .A(n3052), .B(po070), .Z(n3051));
+ AN2 U3028 ( .A(n3053), .B(po099), .Z(n3050));
+ AN2 U3029 ( .A(n3054), .B(n3055), .Z(n3046));
+ AN2 U3030 ( .A(n3018), .B(n3056), .Z(n3043));
+ OR2 U3031 ( .A(n3057), .B(n3058), .Z(n3056));
+ OR2 U3032 ( .A(n3059), .B(n3060), .Z(n3058));
+ AN2 U3033 ( .A(n3061), .B(n3042), .Z(n3060));
+ AN2 U3034 ( .A(n3062), .B(n3063), .Z(n3059));
+ AN2 U3035 ( .A(n3064), .B(n3049), .Z(n3062));
+ AN2 U3036 ( .A(n3065), .B(n3066), .Z(n3057));
+ OR2 U3037 ( .A(n3067), .B(n3068), .Z(n3023));
+ OR2 U3038 ( .A(n3069), .B(n3070), .Z(n3068));
+ AN2 U3039 ( .A(n3071), .B(n3072), .Z(n3070));
+ AN2 U3040 ( .A(n3053), .B(n3073), .Z(n3069));
+ OR2 U3041 ( .A(n3074), .B(n3075), .Z(n3067));
+ AN2 U3042 ( .A(n3076), .B(n3077), .Z(n3075));
+ OR2 U3043 ( .A(n3078), .B(n3079), .Z(n3077));
+ AN2 U3044 ( .A(n3080), .B(n3066), .Z(n3078));
+ AN2 U3045 ( .A(n3081), .B(n3061), .Z(n3074));
+ AN2 U3046 ( .A(n3082), .B(n3038), .Z(n3081));
+ AN2 U3047 ( .A(n3083), .B(n3084), .Z(n3019));
+ OR2 U3048 ( .A(n3085), .B(n3086), .Z(n3084));
+ OR2 U3049 ( .A(n3087), .B(n3088), .Z(n3086));
+ OR2 U3050 ( .A(n3089), .B(n3090), .Z(n3088));
+ AN2 U3051 ( .A(n3091), .B(n3049), .Z(n3089));
+ OR2 U3052 ( .A(n3092), .B(n3093), .Z(n3087));
+ AN2 U3053 ( .A(n3015), .B(n3094), .Z(n3093));
+ OR2 U3054 ( .A(n3095), .B(n3096), .Z(n3094));
+ OR2 U3055 ( .A(n3097), .B(n3098), .Z(n3096));
+ AN2 U3056 ( .A(n3099), .B(n3100), .Z(n3098));
+ AN2 U3057 ( .A(po010), .B(po070), .Z(n3099));
+ AN2 U3058 ( .A(n3101), .B(pi192), .Z(n3097));
+ AN2 U3059 ( .A(n3041), .B(n3038), .Z(n3101));
+ OR2 U3060 ( .A(n3102), .B(n3103), .Z(n3041));
+ AN2 U3061 ( .A(n3104), .B(pi166), .Z(n3103));
+ AN2 U3062 ( .A(n3037), .B(n3049), .Z(n3104));
+ AN2 U3063 ( .A(n3105), .B(n3106), .Z(n3102));
+ OR2 U3064 ( .A(n3107), .B(n3042), .Z(n3105));
+ AN2 U3065 ( .A(po010), .B(n3108), .Z(n3107));
+ AN2 U3066 ( .A(n3079), .B(n3109), .Z(n3095));
+ OR2 U3067 ( .A(n3110), .B(n3111), .Z(n3079));
+ AN2 U3068 ( .A(n3071), .B(n3112), .Z(n3111));
+ AN2 U3069 ( .A(n3065), .B(n3113), .Z(n3110));
+ OR2 U3070 ( .A(n3114), .B(n3066), .Z(n3113));
+ AN2 U3071 ( .A(po010), .B(n3115), .Z(n3114));
+ AN2 U3072 ( .A(n3018), .B(n3116), .Z(n3092));
+ OR2 U3073 ( .A(n3117), .B(n3118), .Z(n3116));
+ AN2 U3074 ( .A(n3065), .B(n3119), .Z(n3118));
+ AN2 U3075 ( .A(n3063), .B(n3120), .Z(n3117));
+ OR2 U3076 ( .A(n3121), .B(n3122), .Z(n3085));
+ OR2 U3077 ( .A(n3123), .B(n3124), .Z(n3122));
+ AN2 U3078 ( .A(n3125), .B(n3055), .Z(n3124));
+ AN2 U3079 ( .A(n3076), .B(n3112), .Z(n3125));
+ AN2 U3080 ( .A(n3126), .B(n3127), .Z(n3123));
+ AN2 U3081 ( .A(n3033), .B(n3037), .Z(n3126));
+ AN2 U3082 ( .A(n3080), .B(n3072), .Z(n3121));
+ AN2 U3083 ( .A(n3119), .B(n3018), .Z(n3072));
+ AN2 U3084 ( .A(n3128), .B(n3129), .Z(n3005));
+ OR2 U3085 ( .A(n3130), .B(n3131), .Z(n3129));
+ OR2 U3086 ( .A(n3132), .B(n3133), .Z(n3131));
+ AN2 U3087 ( .A(n3134), .B(pi192), .Z(n3133));
+ AN2 U3088 ( .A(n3135), .B(n3136), .Z(n3134));
+ OR2 U3089 ( .A(n3137), .B(po044), .Z(n3135));
+ AN2 U3090 ( .A(n3138), .B(n2886), .Z(n3137));
+ AN2 U3091 ( .A(n3139), .B(n2837), .Z(n3132));
+ AN2 U3092 ( .A(n3140), .B(n3141), .Z(n3139));
+ OR2 U3093 ( .A(n3142), .B(po044), .Z(n3140));
+ AN2 U3094 ( .A(n3143), .B(n2886), .Z(n3142));
+ AN2 U3095 ( .A(n3144), .B(n3145), .Z(n3130));
+ OR2 U3096 ( .A(n3146), .B(n3147), .Z(n3145));
+ IV2 U3097 ( .A(n3012), .Z(n3144));
+ AN2 U3098 ( .A(n3148), .B(n3149), .Z(n3128));
+ OR2 U3099 ( .A(n3150), .B(n3018), .Z(n3149));
+ OR2 U3100 ( .A(n3015), .B(n3151), .Z(n3148));
+ IV2 U3101 ( .A(n3150), .Z(n3151));
+ OR2 U3102 ( .A(n3152), .B(n3153), .Z(n3150));
+ AN2 U3103 ( .A(n3021), .B(n3154), .Z(n3153));
+ AN2 U3104 ( .A(n3155), .B(n3083), .Z(n3152));
+ IV2 U3105 ( .A(n3154), .Z(n3155));
+ OR2 U3106 ( .A(n3156), .B(n3157), .Z(n3154));
+ OR2 U3107 ( .A(n3091), .B(n3158), .Z(n3157));
+ OR2 U3108 ( .A(n3159), .B(n3160), .Z(n3158));
+ AN2 U3109 ( .A(n3161), .B(n3049), .Z(n3160));
+ OR2 U3110 ( .A(n3162), .B(n3029), .Z(n3161));
+ OR2 U3111 ( .A(n3163), .B(n3164), .Z(n3029));
+ AN2 U3112 ( .A(po099), .B(n3165), .Z(n3164));
+ OR2 U3113 ( .A(n3166), .B(n3167), .Z(n3165));
+ OR2 U3114 ( .A(n3168), .B(n3169), .Z(n3167));
+ AN2 U3115 ( .A(n3170), .B(pi192), .Z(n3169));
+ AN2 U3116 ( .A(n3038), .B(n3171), .Z(n3170));
+ AN2 U3117 ( .A(n3054), .B(n2837), .Z(n3168));
+ AN2 U3118 ( .A(n3172), .B(n3173), .Z(n3166));
+ AN2 U3119 ( .A(n3015), .B(n3109), .Z(n3172));
+ AN2 U3120 ( .A(n3100), .B(n3018), .Z(n3163));
+ AN2 U3121 ( .A(n3015), .B(n3174), .Z(n3162));
+ OR2 U3122 ( .A(n3175), .B(n3176), .Z(n3174));
+ AN2 U3123 ( .A(n3054), .B(n3173), .Z(n3176));
+ AN2 U3124 ( .A(n3177), .B(n3109), .Z(n3054));
+ AN2 U3125 ( .A(n3178), .B(n3064), .Z(n3175));
+ AN2 U3126 ( .A(n3038), .B(n3037), .Z(n3178));
+ AN2 U3127 ( .A(po010), .B(n3179), .Z(n3159));
+ OR2 U3128 ( .A(n3090), .B(n3180), .Z(n3179));
+ OR2 U3129 ( .A(n3181), .B(n3182), .Z(n3180));
+ AN2 U3130 ( .A(n3053), .B(n3183), .Z(n3182));
+ OR2 U3131 ( .A(n3184), .B(n3119), .Z(n3183));
+ AN2 U3132 ( .A(pi141), .B(n3015), .Z(n3184));
+ AN2 U3133 ( .A(n3109), .B(n3065), .Z(n3053));
+ AN2 U3134 ( .A(n3185), .B(n3061), .Z(n3181));
+ AN2 U3135 ( .A(n3186), .B(n3038), .Z(n3185));
+ OR2 U3136 ( .A(n3187), .B(n3063), .Z(n3186));
+ AN2 U3137 ( .A(pi033), .B(n3015), .Z(n3187));
+ OR2 U3138 ( .A(n3188), .B(n3189), .Z(n3090));
+ AN2 U3139 ( .A(n3190), .B(n3065), .Z(n3189));
+ AN2 U3140 ( .A(n3073), .B(n3076), .Z(n3190));
+ AN2 U3141 ( .A(n3191), .B(n3061), .Z(n3188));
+ AN2 U3142 ( .A(n3082), .B(n3033), .Z(n3191));
+ OR2 U3143 ( .A(n3192), .B(n3193), .Z(n3091));
+ OR2 U3144 ( .A(n3194), .B(n3195), .Z(n3193));
+ AN2 U3145 ( .A(n3052), .B(n3018), .Z(n3195));
+ AN2 U3146 ( .A(n3064), .B(n3196), .Z(n3194));
+ OR2 U3147 ( .A(n3197), .B(n3198), .Z(n3196));
+ AN2 U3148 ( .A(n3082), .B(n3199), .Z(n3198));
+ AN2 U3149 ( .A(n3042), .B(n3033), .Z(n3197));
+ OR2 U3150 ( .A(n3200), .B(n3201), .Z(n3192));
+ AN2 U3151 ( .A(n3173), .B(n3202), .Z(n3201));
+ OR2 U3152 ( .A(n3203), .B(n3204), .Z(n3202));
+ AN2 U3153 ( .A(n3073), .B(n3205), .Z(n3204));
+ AN2 U3154 ( .A(n3076), .B(n3066), .Z(n3203));
+ AN2 U3155 ( .A(n3206), .B(po099), .Z(n3200));
+ AN2 U3156 ( .A(po070), .B(n3207), .Z(n3206));
+ OR2 U3157 ( .A(n3208), .B(n3209), .Z(n3156));
+ AN2 U3158 ( .A(n3210), .B(n3055), .Z(n3209));
+ AN2 U3159 ( .A(n3076), .B(n3115), .Z(n3210));
+ AN2 U3160 ( .A(n3211), .B(n3127), .Z(n3208));
+ AN2 U3161 ( .A(n3033), .B(n3108), .Z(n3211));
+ OR2 U3162 ( .A(n3212), .B(n3213), .Z(po098));
+ AN2 U3163 ( .A(n3214), .B(pi192), .Z(n3213));
+ OR2 U3164 ( .A(n3215), .B(n3216), .Z(n3214));
+ AN2 U3165 ( .A(n2832), .B(n2901), .Z(n3216));
+ IV2 U3166 ( .A(n2835), .Z(n2832));
+ AN2 U3167 ( .A(pi200), .B(n2835), .Z(n3215));
+ OR2 U3168 ( .A(n2880), .B(n2876), .Z(n2835));
+ AN2 U3169 ( .A(n3217), .B(n2837), .Z(n3212));
+ OR2 U3170 ( .A(n3218), .B(n3219), .Z(n3217));
+ AN2 U3171 ( .A(n3220), .B(n2847), .Z(n3219));
+ OR2 U3172 ( .A(n3221), .B(n2902), .Z(n3220));
+ AN2 U3173 ( .A(pi200), .B(n2938), .Z(n3221));
+ AN2 U3174 ( .A(n2844), .B(n3222), .Z(n3218));
+ IV2 U3175 ( .A(n2847), .Z(n2844));
+ OR2 U3176 ( .A(n2936), .B(n2978), .Z(n2847));
+ OR2 U3177 ( .A(n3223), .B(n3224), .Z(po097));
+ AN2 U3178 ( .A(n3225), .B(n3226), .Z(n3224));
+ OR2 U3179 ( .A(n3227), .B(n3228), .Z(n3226));
+ OR2 U3180 ( .A(n3229), .B(n3230), .Z(n3228));
+ OR2 U3181 ( .A(n3231), .B(n3232), .Z(n3230));
+ AN2 U3182 ( .A(n3233), .B(n3234), .Z(n3232));
+ AN2 U3183 ( .A(n3235), .B(n3236), .Z(n3231));
+ OR2 U3184 ( .A(n3237), .B(n3238), .Z(n3227));
+ OR2 U3185 ( .A(n3239), .B(n3240), .Z(n3238));
+ AN2 U3186 ( .A(n3241), .B(n3242), .Z(n3240));
+ AN2 U3187 ( .A(n3243), .B(n3244), .Z(n3239));
+ AN2 U3188 ( .A(po082), .B(n3245), .Z(n3237));
+ AN2 U3189 ( .A(n3246), .B(n3247), .Z(n3223));
+ OR2 U3190 ( .A(n3248), .B(n3249), .Z(n3246));
+ AN2 U3191 ( .A(n3250), .B(n3251), .Z(n3249));
+ OR2 U3192 ( .A(n3252), .B(n3253), .Z(po096));
+ AN2 U3193 ( .A(n3254), .B(n3255), .Z(n3252));
+ OR2 U3194 ( .A(n3256), .B(n3257), .Z(n3254));
+ AN2 U3195 ( .A(n3258), .B(n3259), .Z(n3256));
+ AN2 U3196 ( .A(n3260), .B(n3261), .Z(n3258));
+ OR2 U3197 ( .A(n3262), .B(n3263), .Z(n3260));
+ AN2 U3198 ( .A(n3264), .B(n3265), .Z(n3262));
+ OR2 U3199 ( .A(n3266), .B(n3267), .Z(po095));
+ OR2 U3200 ( .A(n3268), .B(n3269), .Z(n3267));
+ AN2 U3201 ( .A(n3270), .B(n3119), .Z(n3269));
+ OR2 U3202 ( .A(n3271), .B(n3272), .Z(n3270));
+ AN2 U3203 ( .A(n3273), .B(n2837), .Z(n3272));
+ AN2 U3204 ( .A(n3065), .B(n3274), .Z(n3271));
+ AN2 U3205 ( .A(n3063), .B(n3275), .Z(n3268));
+ OR2 U3206 ( .A(n3276), .B(n3277), .Z(n3275));
+ AN2 U3207 ( .A(n3273), .B(pi192), .Z(n3277));
+ AN2 U3208 ( .A(n3061), .B(n3274), .Z(n3276));
+ OR2 U3209 ( .A(n3278), .B(n3279), .Z(n3266));
+ AN2 U3210 ( .A(n3280), .B(n3281), .Z(n3279));
+ OR2 U3211 ( .A(n3282), .B(n3100), .Z(n3281));
+ AN2 U3212 ( .A(n3283), .B(n3284), .Z(n3278));
+ OR2 U3213 ( .A(n3285), .B(n3052), .Z(n3283));
+ AN2 U3214 ( .A(n3286), .B(n3287), .Z(n3052));
+ AN2 U3215 ( .A(po099), .B(n3207), .Z(n3285));
+ AN2 U3216 ( .A(n3288), .B(n3289), .Z(po094));
+ OR2 U3217 ( .A(n3290), .B(n3291), .Z(n3289));
+ OR2 U3218 ( .A(n3234), .B(n3292), .Z(n3288));
+ OR2 U3219 ( .A(n3293), .B(n3294), .Z(po093));
+ AN2 U3220 ( .A(n3295), .B(n3296), .Z(n3294));
+ OR2 U3221 ( .A(n3297), .B(n3298), .Z(n3296));
+ AN2 U3222 ( .A(n3299), .B(n3300), .Z(n3297));
+ AN2 U3223 ( .A(n3301), .B(n3302), .Z(n3293));
+ IV2 U3224 ( .A(n3303), .Z(n3302));
+ AN2 U3225 ( .A(n3304), .B(n3299), .Z(n3303));
+ OR2 U3226 ( .A(n3305), .B(n3306), .Z(n3299));
+ OR2 U3227 ( .A(n3300), .B(n3298), .Z(n3304));
+ AN2 U3228 ( .A(n3305), .B(n3306), .Z(n3298));
+ OR2 U3229 ( .A(n3307), .B(n3308), .Z(po090));
+ OR2 U3230 ( .A(n3309), .B(n3310), .Z(n3308));
+ AN2 U3231 ( .A(n3311), .B(n3312), .Z(n3310));
+ AN2 U3232 ( .A(n3313), .B(n3314), .Z(n3309));
+ OR2 U3233 ( .A(n3315), .B(n3316), .Z(n3313));
+ OR2 U3234 ( .A(n3317), .B(n3318), .Z(n3316));
+ AN2 U3235 ( .A(n3319), .B(n3320), .Z(n3315));
+ OR2 U3236 ( .A(n3321), .B(n3322), .Z(n3319));
+ OR2 U3237 ( .A(n3323), .B(n3324), .Z(n3307));
+ AN2 U3238 ( .A(n3325), .B(n3326), .Z(n3324));
+ AN2 U3239 ( .A(n3327), .B(n3328), .Z(n3323));
+ OR2 U3240 ( .A(n3329), .B(n3330), .Z(n3327));
+ OR2 U3241 ( .A(n3331), .B(n3332), .Z(po088));
+ IV2 U3242 ( .A(n3333), .Z(n3332));
+ OR2 U3243 ( .A(n3334), .B(n3335), .Z(n3333));
+ AN2 U3244 ( .A(n3335), .B(n3334), .Z(n3331));
+ AN2 U3245 ( .A(n3336), .B(n3337), .Z(n3334));
+ OR2 U3246 ( .A(n3338), .B(n3339), .Z(n3337));
+ IV2 U3247 ( .A(n3340), .Z(n3338));
+ OR2 U3248 ( .A(n3341), .B(n3340), .Z(n3336));
+ OR2 U3249 ( .A(n3342), .B(n3343), .Z(n3340));
+ AN2 U3250 ( .A(n3291), .B(n3250), .Z(n3343));
+ AN2 U3251 ( .A(n3344), .B(n3292), .Z(n3342));
+ OR2 U3252 ( .A(n3345), .B(n3346), .Z(n3335));
+ IV2 U3253 ( .A(n3347), .Z(n3346));
+ OR2 U3254 ( .A(n3348), .B(n3349), .Z(n3347));
+ AN2 U3255 ( .A(n3349), .B(n3348), .Z(n3345));
+ AN2 U3256 ( .A(n3350), .B(n3351), .Z(n3348));
+ OR2 U3257 ( .A(n3352), .B(n3353), .Z(n3351));
+ IV2 U3258 ( .A(n3354), .Z(n3353));
+ OR2 U3259 ( .A(n3354), .B(n3355), .Z(n3350));
+ OR2 U3260 ( .A(n3356), .B(n3357), .Z(n3354));
+ OR2 U3261 ( .A(n3358), .B(n3359), .Z(n3357));
+ AN2 U3262 ( .A(n3360), .B(n3361), .Z(n3359));
+ AN2 U3263 ( .A(n3362), .B(n3363), .Z(n3360));
+ OR2 U3264 ( .A(n3364), .B(n3365), .Z(n3362));
+ OR2 U3265 ( .A(n3366), .B(n3367), .Z(n3365));
+ AN2 U3266 ( .A(n3368), .B(n3369), .Z(n3367));
+ AN2 U3267 ( .A(n3370), .B(n3371), .Z(n3368));
+ AN2 U3268 ( .A(n3372), .B(n3373), .Z(n3366));
+ AN2 U3269 ( .A(n3374), .B(n3375), .Z(n3372));
+ OR2 U3270 ( .A(n3376), .B(n3377), .Z(n3374));
+ OR2 U3271 ( .A(n3378), .B(n3379), .Z(n3377));
+ AN2 U3272 ( .A(n2837), .B(n3380), .Z(n3379));
+ AN2 U3273 ( .A(pi060), .B(n3381), .Z(n3378));
+ AN2 U3274 ( .A(n3382), .B(n3369), .Z(n3364));
+ AN2 U3275 ( .A(n3369), .B(n3383), .Z(n3358));
+ OR2 U3276 ( .A(n3384), .B(n3385), .Z(n3383));
+ OR2 U3277 ( .A(n3386), .B(n3387), .Z(n3385));
+ AN2 U3278 ( .A(n3370), .B(n3388), .Z(n3387));
+ OR2 U3279 ( .A(n3389), .B(n3390), .Z(n3388));
+ AN2 U3280 ( .A(n3391), .B(n3392), .Z(n3390));
+ AN2 U3281 ( .A(n3393), .B(n3394), .Z(n3386));
+ OR2 U3282 ( .A(n3395), .B(n3396), .Z(n3394));
+ OR2 U3283 ( .A(n3321), .B(n3397), .Z(n3396));
+ AN2 U3284 ( .A(n3398), .B(n3399), .Z(n3397));
+ AN2 U3285 ( .A(n3400), .B(n3401), .Z(n3395));
+ OR2 U3286 ( .A(n3402), .B(n3371), .Z(n3400));
+ AN2 U3287 ( .A(n3403), .B(n3404), .Z(n3402));
+ AN2 U3288 ( .A(pi060), .B(po071), .Z(n3403));
+ OR2 U3289 ( .A(n3405), .B(n3406), .Z(n3384));
+ AN2 U3290 ( .A(n3407), .B(n3363), .Z(n3406));
+ AN2 U3291 ( .A(n3408), .B(n3401), .Z(n3407));
+ OR2 U3292 ( .A(n3409), .B(n3410), .Z(n3408));
+ AN2 U3293 ( .A(n3411), .B(n3412), .Z(n3409));
+ OR2 U3294 ( .A(n3413), .B(n3414), .Z(n3411));
+ AN2 U3295 ( .A(n3415), .B(n3370), .Z(n3414));
+ OR2 U3296 ( .A(n3416), .B(n3417), .Z(n3415));
+ AN2 U3297 ( .A(n3418), .B(n3381), .Z(n3413));
+ AN2 U3298 ( .A(n3393), .B(n3419), .Z(n3418));
+ AN2 U3299 ( .A(n3420), .B(po027), .Z(n3405));
+ OR2 U3300 ( .A(n3421), .B(n3422), .Z(n3420));
+ OR2 U3301 ( .A(n3423), .B(n3424), .Z(n3422));
+ AN2 U3302 ( .A(n3410), .B(n3361), .Z(n3424));
+ IV2 U3303 ( .A(n3425), .Z(n3410));
+ AN2 U3304 ( .A(n3426), .B(n3401), .Z(n3423));
+ OR2 U3305 ( .A(n3427), .B(n3382), .Z(n3426));
+ IV2 U3306 ( .A(n3428), .Z(n3382));
+ OR2 U3307 ( .A(n3429), .B(n3430), .Z(n3421));
+ AN2 U3308 ( .A(n3431), .B(n3370), .Z(n3430));
+ AN2 U3309 ( .A(n3393), .B(n3432), .Z(n3429));
+ OR2 U3310 ( .A(n3433), .B(n3434), .Z(n3432));
+ AN2 U3311 ( .A(po071), .B(n3419), .Z(n3434));
+ IV2 U3312 ( .A(n3435), .Z(n3369));
+ OR2 U3313 ( .A(n3436), .B(n3375), .Z(n3435));
+ AN2 U3314 ( .A(n3437), .B(n3438), .Z(n3436));
+ AN2 U3315 ( .A(n3439), .B(n3440), .Z(n3438));
+ OR2 U3316 ( .A(n3361), .B(n3441), .Z(n3440));
+ AN2 U3317 ( .A(n3442), .B(n3443), .Z(n3441));
+ OR2 U3318 ( .A(n3444), .B(n3445), .Z(n3443));
+ OR2 U3319 ( .A(n3370), .B(n3446), .Z(n3445));
+ OR2 U3320 ( .A(n3371), .B(n3380), .Z(n3444));
+ AN2 U3321 ( .A(n3447), .B(n3448), .Z(n3442));
+ OR2 U3322 ( .A(po027), .B(n3449), .Z(n3448));
+ AN2 U3323 ( .A(n3450), .B(n3428), .Z(n3449));
+ OR2 U3324 ( .A(n3371), .B(n3451), .Z(n3428));
+ OR2 U3325 ( .A(n3370), .B(n3412), .Z(n3450));
+ OR2 U3326 ( .A(n3363), .B(n3425), .Z(n3447));
+ OR2 U3327 ( .A(n3427), .B(n3452), .Z(n3425));
+ AN2 U3328 ( .A(n3453), .B(n3412), .Z(n3452));
+ AN2 U3329 ( .A(n3371), .B(n3451), .Z(n3427));
+ OR2 U3330 ( .A(n3401), .B(n3454), .Z(n3439));
+ IV2 U3331 ( .A(n3455), .Z(n3454));
+ AN2 U3332 ( .A(n3412), .B(n3456), .Z(n3455));
+ OR2 U3333 ( .A(n3457), .B(n3458), .Z(n3456));
+ AN2 U3334 ( .A(n3392), .B(n3393), .Z(n3458));
+ AN2 U3335 ( .A(n3459), .B(n3460), .Z(n3437));
+ OR2 U3336 ( .A(n3457), .B(n3461), .Z(n3460));
+ AN2 U3337 ( .A(n3462), .B(n3463), .Z(n3459));
+ OR2 U3338 ( .A(n3464), .B(n3370), .Z(n3463));
+ IV2 U3339 ( .A(n3465), .Z(n3464));
+ OR2 U3340 ( .A(n3389), .B(n3431), .Z(n3465));
+ AN2 U3341 ( .A(n3466), .B(n3419), .Z(n3431));
+ AN2 U3342 ( .A(n3467), .B(n3468), .Z(n3389));
+ IV2 U3343 ( .A(n3469), .Z(n3468));
+ OR2 U3344 ( .A(n3417), .B(n3470), .Z(n3469));
+ AN2 U3345 ( .A(n3471), .B(n3399), .Z(n3470));
+ OR2 U3346 ( .A(n3371), .B(n3446), .Z(n3471));
+ OR2 U3347 ( .A(n3472), .B(n3393), .Z(n3462));
+ AN2 U3348 ( .A(n3473), .B(n3474), .Z(n3472));
+ AN2 U3349 ( .A(n3475), .B(n3476), .Z(n3474));
+ OR2 U3350 ( .A(n3412), .B(n3477), .Z(n3476));
+ AN2 U3351 ( .A(n3478), .B(n3261), .Z(n3475));
+ IV2 U3352 ( .A(n3479), .Z(n3478));
+ AN2 U3353 ( .A(n3361), .B(n3480), .Z(n3479));
+ AN2 U3354 ( .A(n3481), .B(n3482), .Z(n3473));
+ OR2 U3355 ( .A(n3483), .B(n3380), .Z(n3482));
+ AN2 U3356 ( .A(n3484), .B(n3461), .Z(n3483));
+ OR2 U3357 ( .A(n3371), .B(n3485), .Z(n3484));
+ IV2 U3358 ( .A(n3433), .Z(n3481));
+ OR2 U3359 ( .A(n3486), .B(n3417), .Z(n3433));
+ AN2 U3360 ( .A(n3404), .B(n3381), .Z(n3417));
+ AN2 U3361 ( .A(n3487), .B(n3380), .Z(n3486));
+ AN2 U3362 ( .A(n3488), .B(n3375), .Z(n3356));
+ OR2 U3363 ( .A(n3489), .B(n3490), .Z(n3375));
+ AN2 U3364 ( .A(n3225), .B(n3491), .Z(n3489));
+ OR2 U3365 ( .A(n3492), .B(n3493), .Z(n3491));
+ AN2 U3366 ( .A(n3494), .B(n3495), .Z(n3492));
+ OR2 U3367 ( .A(n3496), .B(n3497), .Z(n3488));
+ OR2 U3368 ( .A(n3498), .B(n3499), .Z(n3497));
+ AN2 U3369 ( .A(n3371), .B(n3500), .Z(n3499));
+ OR2 U3370 ( .A(n3501), .B(n3502), .Z(n3500));
+ OR2 U3371 ( .A(n3503), .B(n3504), .Z(n3502));
+ AN2 U3372 ( .A(n3505), .B(n3401), .Z(n3504));
+ OR2 U3373 ( .A(n3506), .B(n3507), .Z(n3505));
+ AN2 U3374 ( .A(n3508), .B(n3509), .Z(n3507));
+ OR2 U3375 ( .A(n3510), .B(n3511), .Z(n3509));
+ OR2 U3376 ( .A(n3398), .B(n3487), .Z(n3511));
+ AN2 U3377 ( .A(n3512), .B(n2837), .Z(n3487));
+ AN2 U3378 ( .A(n3404), .B(pi060), .Z(n3510));
+ AN2 U3379 ( .A(n3513), .B(po027), .Z(n3506));
+ AN2 U3380 ( .A(n3514), .B(n3515), .Z(n3513));
+ OR2 U3381 ( .A(n3516), .B(n3517), .Z(n3515));
+ OR2 U3382 ( .A(n3321), .B(n3373), .Z(n3514));
+ AN2 U3383 ( .A(n3518), .B(n3467), .Z(n3503));
+ AN2 U3384 ( .A(n3404), .B(n3519), .Z(n3518));
+ OR2 U3385 ( .A(n3520), .B(n3521), .Z(n3501));
+ AN2 U3386 ( .A(n3522), .B(n3517), .Z(n3521));
+ AN2 U3387 ( .A(n3516), .B(n3363), .Z(n3522));
+ AN2 U3388 ( .A(n3373), .B(n3523), .Z(n3520));
+ OR2 U3389 ( .A(n3524), .B(n3525), .Z(n3523));
+ AN2 U3390 ( .A(n3361), .B(n3526), .Z(n3524));
+ OR2 U3391 ( .A(n3527), .B(n3321), .Z(n3526));
+ AN2 U3392 ( .A(n3519), .B(n3528), .Z(n3498));
+ OR2 U3393 ( .A(n3529), .B(n3530), .Z(n3528));
+ OR2 U3394 ( .A(n3392), .B(n3531), .Z(n3530));
+ AN2 U3395 ( .A(n3376), .B(n3412), .Z(n3531));
+ OR2 U3396 ( .A(n3532), .B(n3321), .Z(n3376));
+ AN2 U3397 ( .A(n3533), .B(n3399), .Z(n3532));
+ AN2 U3398 ( .A(n3534), .B(n3381), .Z(n3529));
+ OR2 U3399 ( .A(n3535), .B(n3536), .Z(n3519));
+ AN2 U3400 ( .A(n3537), .B(po027), .Z(n3536));
+ AN2 U3401 ( .A(n3538), .B(n3363), .Z(n3535));
+ AN2 U3402 ( .A(n3517), .B(n3401), .Z(n3538));
+ OR2 U3403 ( .A(n3539), .B(n3540), .Z(n3496));
+ AN2 U3404 ( .A(n3541), .B(n3542), .Z(n3540));
+ OR2 U3405 ( .A(n3543), .B(n3544), .Z(n3542));
+ AN2 U3406 ( .A(n3453), .B(po071), .Z(n3544));
+ AN2 U3407 ( .A(n3480), .B(n3534), .Z(n3543));
+ AN2 U3408 ( .A(n3545), .B(n3546), .Z(n3541));
+ OR2 U3409 ( .A(n3361), .B(n3547), .Z(n3546));
+ AN2 U3410 ( .A(n3508), .B(n3412), .Z(n3547));
+ OR2 U3411 ( .A(n3401), .B(n3548), .Z(n3545));
+ IV2 U3412 ( .A(n3508), .Z(n3548));
+ OR2 U3413 ( .A(n3549), .B(n3550), .Z(n3508));
+ AN2 U3414 ( .A(n3373), .B(n3363), .Z(n3550));
+ AN2 U3415 ( .A(n3517), .B(po027), .Z(n3549));
+ AN2 U3416 ( .A(n3551), .B(n3467), .Z(n3539));
+ AN2 U3417 ( .A(n3552), .B(n3381), .Z(n3551));
+ OR2 U3418 ( .A(n3553), .B(n3554), .Z(n3552));
+ AN2 U3419 ( .A(n3537), .B(n3363), .Z(n3554));
+ AN2 U3420 ( .A(n3555), .B(po027), .Z(n3553));
+ IV2 U3421 ( .A(n3537), .Z(n3555));
+ OR2 U3422 ( .A(n3556), .B(n3557), .Z(n3537));
+ AN2 U3423 ( .A(n3373), .B(n3401), .Z(n3557));
+ AN2 U3424 ( .A(n3517), .B(n3361), .Z(n3556));
+ IV2 U3425 ( .A(n3373), .Z(n3517));
+ OR2 U3426 ( .A(n3558), .B(n3559), .Z(n3373));
+ AN2 U3427 ( .A(n3370), .B(n3560), .Z(n3559));
+ OR2 U3428 ( .A(n3561), .B(n3562), .Z(n3560));
+ OR2 U3429 ( .A(n3361), .B(n3563), .Z(n3562));
+ AN2 U3430 ( .A(n3321), .B(po027), .Z(n3563));
+ OR2 U3431 ( .A(n3564), .B(n3565), .Z(n3561));
+ OR2 U3432 ( .A(n3527), .B(n3566), .Z(n3565));
+ AN2 U3433 ( .A(po027), .B(n3398), .Z(n3527));
+ AN2 U3434 ( .A(n3404), .B(n3567), .Z(n3564));
+ AN2 U3435 ( .A(n3393), .B(n3568), .Z(n3558));
+ OR2 U3436 ( .A(n3569), .B(n3570), .Z(n3568));
+ AN2 U3437 ( .A(n3571), .B(n3401), .Z(n3570));
+ OR2 U3438 ( .A(n3516), .B(n3572), .Z(n3571));
+ AN2 U3439 ( .A(n3419), .B(n3363), .Z(n3572));
+ AN2 U3440 ( .A(po104), .B(n3453), .Z(n3516));
+ AN2 U3441 ( .A(n3573), .B(n3467), .Z(n3569));
+ AN2 U3442 ( .A(n3261), .B(n3533), .Z(n3467));
+ AN2 U3443 ( .A(n3404), .B(po027), .Z(n3573));
+ OR2 U3444 ( .A(n3574), .B(n3575), .Z(n3349));
+ AN2 U3445 ( .A(n3576), .B(n3247), .Z(n3575));
+ IV2 U3446 ( .A(n3577), .Z(n3576));
+ AN2 U3447 ( .A(n3225), .B(n3577), .Z(n3574));
+ OR2 U3448 ( .A(n3578), .B(n3579), .Z(n3577));
+ OR2 U3449 ( .A(n3580), .B(n3581), .Z(n3579));
+ OR2 U3450 ( .A(n3582), .B(n3583), .Z(n3581));
+ AN2 U3451 ( .A(n3584), .B(n2837), .Z(n3583));
+ OR2 U3452 ( .A(n3585), .B(n3586), .Z(n3584));
+ OR2 U3453 ( .A(n3587), .B(n3588), .Z(n3586));
+ AN2 U3454 ( .A(n3589), .B(n3590), .Z(n3588));
+ AN2 U3455 ( .A(n3591), .B(n3592), .Z(n3589));
+ OR2 U3456 ( .A(n3593), .B(n3355), .Z(n3592));
+ AN2 U3457 ( .A(n3594), .B(n3595), .Z(n3591));
+ OR2 U3458 ( .A(n3596), .B(n3597), .Z(n3595));
+ OR2 U3459 ( .A(pi003), .B(n3598), .Z(n3594));
+ AN2 U3460 ( .A(n3599), .B(n3600), .Z(n3587));
+ OR2 U3461 ( .A(n3601), .B(n3602), .Z(n3600));
+ OR2 U3462 ( .A(n3603), .B(n3604), .Z(n3602));
+ AN2 U3463 ( .A(n3605), .B(n3593), .Z(n3604));
+ AN2 U3464 ( .A(n3606), .B(n3607), .Z(n3603));
+ OR2 U3465 ( .A(n3608), .B(n3609), .Z(n3601));
+ AN2 U3466 ( .A(n3610), .B(pi003), .Z(n3609));
+ AN2 U3467 ( .A(n3611), .B(n3612), .Z(n3610));
+ AN2 U3468 ( .A(n3613), .B(n3597), .Z(n3608));
+ OR2 U3469 ( .A(n3614), .B(n3615), .Z(n3613));
+ AN2 U3470 ( .A(n3598), .B(n3616), .Z(n3615));
+ AN2 U3471 ( .A(n3617), .B(n3593), .Z(n3614));
+ AN2 U3472 ( .A(n3618), .B(n3619), .Z(n3585));
+ AN2 U3473 ( .A(n3620), .B(n3590), .Z(n3618));
+ OR2 U3474 ( .A(n3621), .B(n3622), .Z(n3620));
+ OR2 U3475 ( .A(n3494), .B(n3606), .Z(n3622));
+ AN2 U3476 ( .A(pi003), .B(n3623), .Z(n3606));
+ AN2 U3477 ( .A(n3616), .B(po011), .Z(n3623));
+ AN2 U3478 ( .A(n3624), .B(n3625), .Z(n3621));
+ AN2 U3479 ( .A(n3616), .B(n3597), .Z(n3624));
+ AN2 U3480 ( .A(pi192), .B(n3626), .Z(n3582));
+ OR2 U3481 ( .A(n3627), .B(n3628), .Z(n3626));
+ OR2 U3482 ( .A(n3629), .B(n3630), .Z(n3628));
+ AN2 U3483 ( .A(n3631), .B(n3632), .Z(n3630));
+ AN2 U3484 ( .A(n3633), .B(n3634), .Z(n3631));
+ OR2 U3485 ( .A(n3635), .B(n3355), .Z(n3634));
+ AN2 U3486 ( .A(n3636), .B(n3637), .Z(n3633));
+ OR2 U3487 ( .A(n3596), .B(n3638), .Z(n3637));
+ AN2 U3488 ( .A(n3639), .B(n3339), .Z(n3596));
+ OR2 U3489 ( .A(pi098), .B(n3598), .Z(n3636));
+ AN2 U3490 ( .A(n3640), .B(n3641), .Z(n3629));
+ OR2 U3491 ( .A(n3642), .B(n3643), .Z(n3641));
+ OR2 U3492 ( .A(n3644), .B(n3645), .Z(n3643));
+ AN2 U3493 ( .A(n3605), .B(n3635), .Z(n3645));
+ OR2 U3494 ( .A(n3646), .B(n3647), .Z(n3605));
+ AN2 U3495 ( .A(n3648), .B(n3493), .Z(n3647));
+ AN2 U3496 ( .A(n3341), .B(n3639), .Z(n3646));
+ AN2 U3497 ( .A(n3649), .B(n3607), .Z(n3644));
+ OR2 U3498 ( .A(n3650), .B(n3651), .Z(n3642));
+ AN2 U3499 ( .A(n3652), .B(pi098), .Z(n3651));
+ AN2 U3500 ( .A(n3653), .B(n3612), .Z(n3652));
+ AN2 U3501 ( .A(n3654), .B(n3638), .Z(n3650));
+ OR2 U3502 ( .A(n3655), .B(n3656), .Z(n3654));
+ AN2 U3503 ( .A(n3598), .B(n3657), .Z(n3656));
+ OR2 U3504 ( .A(n3658), .B(n3659), .Z(n3598));
+ AN2 U3505 ( .A(n3660), .B(n3493), .Z(n3659));
+ AN2 U3506 ( .A(po011), .B(n3612), .Z(n3660));
+ AN2 U3507 ( .A(n3625), .B(n3661), .Z(n3658));
+ AN2 U3508 ( .A(n3617), .B(n3635), .Z(n3655));
+ AN2 U3509 ( .A(n3625), .B(n3493), .Z(n3617));
+ AN2 U3510 ( .A(n3662), .B(n3619), .Z(n3627));
+ AN2 U3511 ( .A(n3663), .B(n3632), .Z(n3662));
+ OR2 U3512 ( .A(n3664), .B(n3665), .Z(n3663));
+ OR2 U3513 ( .A(n3494), .B(n3649), .Z(n3665));
+ AN2 U3514 ( .A(pi098), .B(n3666), .Z(n3649));
+ AN2 U3515 ( .A(n3657), .B(po011), .Z(n3666));
+ AN2 U3516 ( .A(n3612), .B(n3667), .Z(n3494));
+ AN2 U3517 ( .A(n3668), .B(n3625), .Z(n3664));
+ AN2 U3518 ( .A(n3657), .B(n3638), .Z(n3668));
+ OR2 U3519 ( .A(n3669), .B(n3670), .Z(n3580));
+ AN2 U3520 ( .A(n3671), .B(po011), .Z(n3670));
+ AN2 U3521 ( .A(n3672), .B(n3612), .Z(n3671));
+ AN2 U3522 ( .A(n3673), .B(n3674), .Z(n3672));
+ OR2 U3523 ( .A(pi192), .B(n3675), .Z(n3674));
+ AN2 U3524 ( .A(n3676), .B(n3597), .Z(n3675));
+ OR2 U3525 ( .A(n3677), .B(n3678), .Z(n3676));
+ AN2 U3526 ( .A(n3679), .B(n3680), .Z(n3677));
+ AN2 U3527 ( .A(n3599), .B(n3661), .Z(n3679));
+ OR2 U3528 ( .A(n2837), .B(n3681), .Z(n3673));
+ AN2 U3529 ( .A(n3682), .B(n3638), .Z(n3681));
+ OR2 U3530 ( .A(n3683), .B(n3684), .Z(n3682));
+ AN2 U3531 ( .A(n3685), .B(n3686), .Z(n3683));
+ AN2 U3532 ( .A(n3640), .B(n3661), .Z(n3685));
+ AN2 U3533 ( .A(n3687), .B(n3688), .Z(n3669));
+ OR2 U3534 ( .A(n3689), .B(n3690), .Z(n3687));
+ OR2 U3535 ( .A(n3691), .B(n3692), .Z(n3690));
+ AN2 U3536 ( .A(n3693), .B(n3612), .Z(n3692));
+ AN2 U3537 ( .A(n3619), .B(n3694), .Z(n3693));
+ OR2 U3538 ( .A(n3695), .B(n3696), .Z(n3694));
+ OR2 U3539 ( .A(n3697), .B(n3698), .Z(n3696));
+ AN2 U3540 ( .A(n3699), .B(n3616), .Z(n3698));
+ AN2 U3541 ( .A(n3700), .B(n3657), .Z(n3697));
+ AN2 U3542 ( .A(n3341), .B(n3701), .Z(n3695));
+ AN2 U3543 ( .A(n3493), .B(n3352), .Z(n3619));
+ AN2 U3544 ( .A(n3625), .B(n3702), .Z(n3691));
+ OR2 U3545 ( .A(n3703), .B(n3704), .Z(n3702));
+ AN2 U3546 ( .A(n3705), .B(n3706), .Z(n3704));
+ OR2 U3547 ( .A(n3684), .B(n3707), .Z(n3706));
+ OR2 U3548 ( .A(n3708), .B(n3709), .Z(n3707));
+ AN2 U3549 ( .A(n3710), .B(n3640), .Z(n3709));
+ OR2 U3550 ( .A(n3711), .B(n3712), .Z(n3710));
+ AN2 U3551 ( .A(n3607), .B(n3686), .Z(n3712));
+ AN2 U3552 ( .A(n3493), .B(n3713), .Z(n3711));
+ IV2 U3553 ( .A(n3686), .Z(n3713));
+ AN2 U3554 ( .A(n3653), .B(n3632), .Z(n3708));
+ OR2 U3555 ( .A(n3714), .B(n3715), .Z(n3653));
+ AN2 U3556 ( .A(n3686), .B(n3493), .Z(n3714));
+ AN2 U3557 ( .A(n3635), .B(n3339), .Z(n3686));
+ AN2 U3558 ( .A(n3607), .B(n3716), .Z(n3684));
+ AN2 U3559 ( .A(n3632), .B(n3657), .Z(n3716));
+ AN2 U3560 ( .A(n3717), .B(n3718), .Z(n3703));
+ OR2 U3561 ( .A(n3678), .B(n3719), .Z(n3718));
+ OR2 U3562 ( .A(n3720), .B(n3721), .Z(n3719));
+ AN2 U3563 ( .A(n3722), .B(n3599), .Z(n3721));
+ OR2 U3564 ( .A(n3723), .B(n3724), .Z(n3722));
+ AN2 U3565 ( .A(n3680), .B(n3607), .Z(n3724));
+ AN2 U3566 ( .A(n3493), .B(n3725), .Z(n3723));
+ IV2 U3567 ( .A(n3680), .Z(n3725));
+ AN2 U3568 ( .A(n3611), .B(n3590), .Z(n3720));
+ OR2 U3569 ( .A(n3726), .B(n3715), .Z(n3611));
+ AN2 U3570 ( .A(n3341), .B(n3607), .Z(n3715));
+ AN2 U3571 ( .A(n3680), .B(n3493), .Z(n3726));
+ AN2 U3572 ( .A(n3593), .B(n3339), .Z(n3680));
+ AN2 U3573 ( .A(n3607), .B(n3727), .Z(n3678));
+ AN2 U3574 ( .A(n3590), .B(n3616), .Z(n3727));
+ AN2 U3575 ( .A(n3661), .B(n3352), .Z(n3607));
+ AN2 U3576 ( .A(n3639), .B(n3728), .Z(n3689));
+ OR2 U3577 ( .A(n3729), .B(n3730), .Z(n3728));
+ OR2 U3578 ( .A(n3731), .B(n3732), .Z(n3730));
+ AN2 U3579 ( .A(n3733), .B(pi192), .Z(n3732));
+ AN2 U3580 ( .A(n3640), .B(n3657), .Z(n3733));
+ AN2 U3581 ( .A(n3734), .B(n2837), .Z(n3731));
+ AN2 U3582 ( .A(n3599), .B(n3616), .Z(n3734));
+ IV2 U3583 ( .A(n3590), .Z(n3599));
+ AN2 U3584 ( .A(n3735), .B(n3355), .Z(n3729));
+ OR2 U3585 ( .A(n3339), .B(n3736), .Z(n3735));
+ OR2 U3586 ( .A(n3737), .B(n3738), .Z(n3578));
+ AN2 U3587 ( .A(n3355), .B(n3739), .Z(n3738));
+ OR2 U3588 ( .A(n3740), .B(n3741), .Z(n3739));
+ AN2 U3589 ( .A(n3742), .B(n3625), .Z(n3741));
+ AN2 U3590 ( .A(n3743), .B(n3744), .Z(n3742));
+ OR2 U3591 ( .A(n3661), .B(n3688), .Z(n3744));
+ OR2 U3592 ( .A(po011), .B(n3745), .Z(n3743));
+ AN2 U3593 ( .A(n3493), .B(n3746), .Z(n3745));
+ AN2 U3594 ( .A(n3747), .B(n3639), .Z(n3740));
+ AN2 U3595 ( .A(n3661), .B(n3612), .Z(n3639));
+ AN2 U3596 ( .A(n3736), .B(n3746), .Z(n3747));
+ OR2 U3597 ( .A(n3292), .B(n3344), .Z(n3736));
+ IV2 U3598 ( .A(n3291), .Z(n3292));
+ AN2 U3599 ( .A(n3748), .B(n3648), .Z(n3737));
+ OR2 U3600 ( .A(n3749), .B(n3750), .Z(n3648));
+ AN2 U3601 ( .A(n3625), .B(po011), .Z(n3750));
+ IV2 U3602 ( .A(n3612), .Z(n3625));
+ AN2 U3603 ( .A(n3751), .B(n3688), .Z(n3749));
+ AN2 U3604 ( .A(n3339), .B(n3612), .Z(n3751));
+ OR2 U3605 ( .A(n3752), .B(n3753), .Z(n3612));
+ OR2 U3606 ( .A(n3754), .B(n3755), .Z(n3753));
+ AN2 U3607 ( .A(n3756), .B(n3757), .Z(n3755));
+ OR2 U3608 ( .A(n3758), .B(n3759), .Z(n3752));
+ AN2 U3609 ( .A(n3760), .B(n3761), .Z(n3759));
+ AN2 U3610 ( .A(n3661), .B(n3762), .Z(n3748));
+ OR2 U3611 ( .A(n3763), .B(n3764), .Z(po087));
+ OR2 U3612 ( .A(po042), .B(n3765), .Z(n3764));
+ OR2 U3613 ( .A(po029), .B(po022), .Z(n3765));
+ OR2 U3614 ( .A(n3766), .B(n3767), .Z(n3763));
+ OR2 U3615 ( .A(po080), .B(po056), .Z(n3767));
+ OR2 U3616 ( .A(po105), .B(po083), .Z(n3766));
+ IV2 U3617 ( .A(n3768), .Z(po105));
+ AN2 U3618 ( .A(n3769), .B(n3770), .Z(n3768));
+ AN2 U3619 ( .A(pi034), .B(pi007), .Z(n3770));
+ AN2 U3620 ( .A(pi139), .B(pi120), .Z(n3769));
+ OR2 U3621 ( .A(n3771), .B(n3772), .Z(po086));
+ AN2 U3622 ( .A(n3773), .B(n3774), .Z(n3772));
+ OR2 U3623 ( .A(n3775), .B(n3776), .Z(n3774));
+ AN2 U3624 ( .A(n3777), .B(n3778), .Z(n3771));
+ AN2 U3625 ( .A(n3779), .B(n3780), .Z(n3777));
+ OR2 U3626 ( .A(po025), .B(n3781), .Z(n3779));
+ IV2 U3627 ( .A(n3782), .Z(po083));
+ AN2 U3628 ( .A(n3783), .B(n3784), .Z(n3782));
+ AN2 U3629 ( .A(pi067), .B(pi041), .Z(n3784));
+ AN2 U3630 ( .A(pi104), .B(pi070), .Z(n3783));
+ OR2 U3631 ( .A(n3785), .B(n3786), .Z(po081));
+ AN2 U3632 ( .A(n2862), .B(n3787), .Z(n3786));
+ AN2 U3633 ( .A(n2930), .B(n3788), .Z(n3785));
+ OR2 U3634 ( .A(n3146), .B(n3789), .Z(n3788));
+ OR2 U3635 ( .A(n3790), .B(n3791), .Z(n3789));
+ AN2 U3636 ( .A(n3792), .B(n2901), .Z(n3791));
+ OR2 U3637 ( .A(n3793), .B(n3794), .Z(n3792));
+ AN2 U3638 ( .A(pi192), .B(n2887), .Z(n3794));
+ AN2 U3639 ( .A(n3795), .B(n2974), .Z(n3793));
+ OR2 U3640 ( .A(n3796), .B(po031), .Z(n3795));
+ AN2 U3641 ( .A(n2957), .B(n2837), .Z(n3796));
+ AN2 U3642 ( .A(n3797), .B(n2935), .Z(n3790));
+ AN2 U3643 ( .A(n2946), .B(n2837), .Z(n3797));
+ OR2 U3644 ( .A(n3798), .B(n3799), .Z(po080));
+ OR2 U3645 ( .A(n3800), .B(n3801), .Z(n3799));
+ OR2 U3646 ( .A(n3802), .B(n3803), .Z(n3801));
+ AN2 U3647 ( .A(n3804), .B(n2837), .Z(n3803));
+ OR2 U3648 ( .A(n3805), .B(n3806), .Z(n3804));
+ OR2 U3649 ( .A(n3807), .B(n3808), .Z(n3806));
+ AN2 U3650 ( .A(n3809), .B(n3810), .Z(n3808));
+ AN2 U3651 ( .A(n3811), .B(n3812), .Z(n3807));
+ AN2 U3652 ( .A(n3813), .B(n3814), .Z(n3805));
+ OR2 U3653 ( .A(n3815), .B(n3816), .Z(n3814));
+ OR2 U3654 ( .A(n3817), .B(n3818), .Z(n3813));
+ AN2 U3655 ( .A(pi192), .B(n3819), .Z(n3802));
+ OR2 U3656 ( .A(n3820), .B(n3821), .Z(n3819));
+ OR2 U3657 ( .A(n3822), .B(n3823), .Z(n3821));
+ AN2 U3658 ( .A(n3824), .B(n3825), .Z(n3823));
+ OR2 U3659 ( .A(n3826), .B(n3827), .Z(n3825));
+ IV2 U3660 ( .A(n3828), .Z(n3824));
+ AN2 U3661 ( .A(n3827), .B(n3826), .Z(n3828));
+ OR2 U3662 ( .A(n3829), .B(n3830), .Z(n3826));
+ AN2 U3663 ( .A(n3817), .B(n3171), .Z(n3830));
+ AN2 U3664 ( .A(n3816), .B(pi033), .Z(n3829));
+ IV2 U3665 ( .A(n3817), .Z(n3816));
+ OR2 U3666 ( .A(n3831), .B(n3832), .Z(n3817));
+ AN2 U3667 ( .A(n3833), .B(pi192), .Z(n3832));
+ OR2 U3668 ( .A(n3834), .B(n3835), .Z(n3833));
+ IV2 U3669 ( .A(n3836), .Z(n3835));
+ OR2 U3670 ( .A(n3837), .B(n3838), .Z(n3836));
+ AN2 U3671 ( .A(n3838), .B(n3837), .Z(n3834));
+ AN2 U3672 ( .A(n3839), .B(n3840), .Z(n3837));
+ OR2 U3673 ( .A(n3841), .B(pi013), .Z(n3840));
+ IV2 U3674 ( .A(n3842), .Z(n3841));
+ OR2 U3675 ( .A(n3843), .B(n3842), .Z(n3839));
+ OR2 U3676 ( .A(n3844), .B(n3845), .Z(n3842));
+ AN2 U3677 ( .A(pi026), .B(n3846), .Z(n3845));
+ AN2 U3678 ( .A(pi077), .B(n3847), .Z(n3844));
+ IV2 U3679 ( .A(pi013), .Z(n3843));
+ OR2 U3680 ( .A(n3848), .B(n3849), .Z(n3838));
+ AN2 U3681 ( .A(n3850), .B(n3136), .Z(n3849));
+ AN2 U3682 ( .A(n3851), .B(pi088), .Z(n3848));
+ IV2 U3683 ( .A(n3850), .Z(n3851));
+ OR2 U3684 ( .A(n3852), .B(n3853), .Z(n3850));
+ IV2 U3685 ( .A(n3854), .Z(n3853));
+ OR2 U3686 ( .A(n3855), .B(pi157), .Z(n3854));
+ AN2 U3687 ( .A(pi157), .B(n3855), .Z(n3852));
+ IV2 U3688 ( .A(pi137), .Z(n3855));
+ AN2 U3689 ( .A(n3856), .B(n3857), .Z(n3827));
+ OR2 U3690 ( .A(n3858), .B(pi096), .Z(n3857));
+ IV2 U3691 ( .A(n3859), .Z(n3858));
+ OR2 U3692 ( .A(n3859), .B(n3199), .Z(n3856));
+ OR2 U3693 ( .A(n3860), .B(n3861), .Z(n3859));
+ AN2 U3694 ( .A(pi166), .B(n3862), .Z(n3861));
+ IV2 U3695 ( .A(pi175), .Z(n3862));
+ AN2 U3696 ( .A(pi175), .B(n3106), .Z(n3860));
+ OR2 U3697 ( .A(n3863), .B(n3864), .Z(n3822));
+ AN2 U3698 ( .A(n3865), .B(n3866), .Z(n3864));
+ IV2 U3699 ( .A(n3867), .Z(n3863));
+ OR2 U3700 ( .A(n3866), .B(n3865), .Z(n3867));
+ OR2 U3701 ( .A(n3868), .B(n3869), .Z(n3865));
+ AN2 U3702 ( .A(n3811), .B(n3870), .Z(n3869));
+ IV2 U3703 ( .A(n3810), .Z(n3811));
+ AN2 U3704 ( .A(pi016), .B(n3810), .Z(n3868));
+ OR2 U3705 ( .A(n3871), .B(n3872), .Z(n3810));
+ OR2 U3706 ( .A(n3873), .B(n3874), .Z(n3872));
+ AN2 U3707 ( .A(n3875), .B(pi148), .Z(n3874));
+ OR2 U3708 ( .A(n3876), .B(n3877), .Z(n3875));
+ AN2 U3709 ( .A(n3878), .B(pi135), .Z(n3877));
+ AN2 U3710 ( .A(n3879), .B(n3880), .Z(n3876));
+ AN2 U3711 ( .A(n3881), .B(n3882), .Z(n3873));
+ IV2 U3712 ( .A(pi148), .Z(n3882));
+ OR2 U3713 ( .A(n3883), .B(n3884), .Z(n3881));
+ AN2 U3714 ( .A(n3879), .B(pi135), .Z(n3884));
+ OR2 U3715 ( .A(n3885), .B(n3886), .Z(n3879));
+ AN2 U3716 ( .A(n3887), .B(n3888), .Z(n3886));
+ AN2 U3717 ( .A(n3889), .B(n3890), .Z(n3885));
+ AN2 U3718 ( .A(n3878), .B(n3880), .Z(n3883));
+ OR2 U3719 ( .A(n3891), .B(n3892), .Z(n3878));
+ AN2 U3720 ( .A(n3887), .B(n3890), .Z(n3892));
+ AN2 U3721 ( .A(n3889), .B(n3888), .Z(n3891));
+ IV2 U3722 ( .A(n3887), .Z(n3889));
+ OR2 U3723 ( .A(n3893), .B(n3894), .Z(n3887));
+ AN2 U3724 ( .A(n3895), .B(n3896), .Z(n3894));
+ AN2 U3725 ( .A(n3897), .B(pi005), .Z(n3893));
+ IV2 U3726 ( .A(n3895), .Z(n3897));
+ OR2 U3727 ( .A(n3898), .B(n3899), .Z(n3895));
+ AN2 U3728 ( .A(pi069), .B(n3900), .Z(n3899));
+ IV2 U3729 ( .A(pi072), .Z(n3900));
+ AN2 U3730 ( .A(pi072), .B(n3901), .Z(n3898));
+ AN2 U3731 ( .A(n3902), .B(n3903), .Z(n3866));
+ OR2 U3732 ( .A(n3904), .B(pi045), .Z(n3903));
+ IV2 U3733 ( .A(n3905), .Z(n3902));
+ AN2 U3734 ( .A(n3904), .B(pi045), .Z(n3905));
+ AN2 U3735 ( .A(n3906), .B(n3907), .Z(n3904));
+ OR2 U3736 ( .A(n3908), .B(pi158), .Z(n3907));
+ OR2 U3737 ( .A(n3909), .B(pi079), .Z(n3906));
+ OR2 U3738 ( .A(n3910), .B(n3911), .Z(n3820));
+ AN2 U3739 ( .A(n3912), .B(n3913), .Z(n3911));
+ AN2 U3740 ( .A(n3534), .B(n3914), .Z(n3912));
+ AN2 U3741 ( .A(pi118), .B(n3915), .Z(n3910));
+ OR2 U3742 ( .A(n3916), .B(n3917), .Z(n3915));
+ AN2 U3743 ( .A(n3918), .B(pi060), .Z(n3917));
+ AN2 U3744 ( .A(n3919), .B(n3534), .Z(n3916));
+ AN2 U3745 ( .A(n3920), .B(n3921), .Z(n3919));
+ AN2 U3746 ( .A(n3922), .B(n3923), .Z(n3800));
+ OR2 U3747 ( .A(n3924), .B(n3925), .Z(n3923));
+ OR2 U3748 ( .A(n3321), .B(n3926), .Z(n3925));
+ AN2 U3749 ( .A(n3927), .B(n3928), .Z(n3924));
+ AN2 U3750 ( .A(pi050), .B(pi118), .Z(n3928));
+ AN2 U3751 ( .A(pi196), .B(n3534), .Z(n3927));
+ OR2 U3752 ( .A(n3929), .B(n3930), .Z(n3798));
+ OR2 U3753 ( .A(n3931), .B(n3932), .Z(n3930));
+ AN2 U3754 ( .A(n3933), .B(n3533), .Z(n3932));
+ AN2 U3755 ( .A(n3934), .B(n3913), .Z(n3933));
+ OR2 U3756 ( .A(n3918), .B(n3935), .Z(n3934));
+ OR2 U3757 ( .A(n3936), .B(n3937), .Z(n3935));
+ AN2 U3758 ( .A(n3938), .B(n3921), .Z(n3937));
+ AN2 U3759 ( .A(n3920), .B(n3261), .Z(n3938));
+ AN2 U3760 ( .A(n3939), .B(n3922), .Z(n3936));
+ AN2 U3761 ( .A(pi196), .B(n3940), .Z(n3939));
+ AN2 U3762 ( .A(n3922), .B(n3941), .Z(n3918));
+ AN2 U3763 ( .A(n3942), .B(n3943), .Z(n3941));
+ AN2 U3764 ( .A(n3944), .B(n3945), .Z(n3931));
+ AN2 U3765 ( .A(pi204), .B(n3946), .Z(n3944));
+ IV2 U3766 ( .A(n3947), .Z(n3946));
+ AN2 U3767 ( .A(n3948), .B(n3261), .Z(n3929));
+ OR2 U3768 ( .A(n3949), .B(n3950), .Z(n3948));
+ AN2 U3769 ( .A(n3947), .B(n3951), .Z(n3950));
+ AN2 U3770 ( .A(n3952), .B(n3953), .Z(n3947));
+ IV2 U3771 ( .A(n3954), .Z(n3953));
+ AN2 U3772 ( .A(n3955), .B(n3956), .Z(n3954));
+ OR2 U3773 ( .A(n3956), .B(n3955), .Z(n3952));
+ OR2 U3774 ( .A(n3957), .B(n3958), .Z(n3955));
+ AN2 U3775 ( .A(n3959), .B(n3960), .Z(n3958));
+ IV2 U3776 ( .A(pi009), .Z(n3960));
+ AN2 U3777 ( .A(pi009), .B(n3961), .Z(n3957));
+ AN2 U3778 ( .A(n3962), .B(n3963), .Z(n3956));
+ OR2 U3779 ( .A(n3964), .B(pi129), .Z(n3963));
+ IV2 U3780 ( .A(n3965), .Z(n3964));
+ OR2 U3781 ( .A(n3965), .B(n3966), .Z(n3962));
+ OR2 U3782 ( .A(n3967), .B(n3968), .Z(n3965));
+ AN2 U3783 ( .A(pi138), .B(n3969), .Z(n3968));
+ AN2 U3784 ( .A(pi169), .B(n3970), .Z(n3967));
+ IV2 U3785 ( .A(pi138), .Z(n3970));
+ AN2 U3786 ( .A(n3971), .B(n3533), .Z(n3949));
+ AN2 U3787 ( .A(n3914), .B(pi118), .Z(n3971));
+ OR2 U3788 ( .A(n3972), .B(n3973), .Z(n3914));
+ AN2 U3789 ( .A(n3920), .B(n3922), .Z(n3973));
+ IV2 U3790 ( .A(n3921), .Z(n3922));
+ AN2 U3791 ( .A(n3921), .B(n3974), .Z(n3972));
+ IV2 U3792 ( .A(n3920), .Z(n3974));
+ OR2 U3793 ( .A(n3975), .B(n3976), .Z(n3920));
+ AN2 U3794 ( .A(pi050), .B(n3942), .Z(n3976));
+ AN2 U3795 ( .A(pi196), .B(n3943), .Z(n3975));
+ OR2 U3796 ( .A(n3977), .B(n3978), .Z(n3921));
+ AN2 U3797 ( .A(n3979), .B(pi192), .Z(n3978));
+ OR2 U3798 ( .A(n3980), .B(n3981), .Z(n3979));
+ AN2 U3799 ( .A(n3982), .B(n3983), .Z(n3981));
+ IV2 U3800 ( .A(n3984), .Z(n3980));
+ OR2 U3801 ( .A(n3983), .B(n3982), .Z(n3984));
+ OR2 U3802 ( .A(n3985), .B(n3986), .Z(n3982));
+ IV2 U3803 ( .A(n3987), .Z(n3986));
+ OR2 U3804 ( .A(n3988), .B(n3989), .Z(n3987));
+ AN2 U3805 ( .A(n3988), .B(n3989), .Z(n3985));
+ AN2 U3806 ( .A(n3990), .B(n3991), .Z(n3988));
+ OR2 U3807 ( .A(n3992), .B(pi039), .Z(n3991));
+ OR2 U3808 ( .A(n3993), .B(pi004), .Z(n3990));
+ IV2 U3809 ( .A(pi039), .Z(n3993));
+ AN2 U3810 ( .A(n3994), .B(n3995), .Z(n3983));
+ OR2 U3811 ( .A(n3996), .B(pi068), .Z(n3995));
+ IV2 U3812 ( .A(n3997), .Z(n3996));
+ OR2 U3813 ( .A(n3997), .B(n3998), .Z(n3994));
+ OR2 U3814 ( .A(n3999), .B(n4000), .Z(n3997));
+ AN2 U3815 ( .A(pi098), .B(n4001), .Z(n4000));
+ AN2 U3816 ( .A(pi171), .B(n3638), .Z(n3999));
+ OR2 U3817 ( .A(pi037), .B(pi043), .Z(po078));
+ OR2 U3818 ( .A(n4002), .B(n4003), .Z(po077));
+ AN2 U3819 ( .A(n4004), .B(n4005), .Z(n4003));
+ AN2 U3820 ( .A(n4006), .B(n4007), .Z(n4002));
+ OR2 U3821 ( .A(n4008), .B(n4009), .Z(n4007));
+ IV2 U3822 ( .A(pi090), .Z(po076));
+ OR2 U3823 ( .A(n4010), .B(n4011), .Z(po075));
+ AN2 U3824 ( .A(n4012), .B(n4013), .Z(n4011));
+ OR2 U3825 ( .A(n4014), .B(n4015), .Z(n4012));
+ OR2 U3826 ( .A(n4016), .B(n4017), .Z(n4015));
+ OR2 U3827 ( .A(n4018), .B(n4019), .Z(n4014));
+ AN2 U3828 ( .A(n4020), .B(n3314), .Z(n4019));
+ OR2 U3829 ( .A(n4021), .B(n4022), .Z(n4020));
+ AN2 U3830 ( .A(n3926), .B(n3328), .Z(n4022));
+ OR2 U3831 ( .A(n3265), .B(n3326), .Z(n3328));
+ AN2 U3832 ( .A(n4023), .B(pi204), .Z(n4021));
+ AN2 U3833 ( .A(n3312), .B(n3261), .Z(n4023));
+ OR2 U3834 ( .A(n4024), .B(n4025), .Z(n3312));
+ AN2 U3835 ( .A(n3326), .B(n4026), .Z(n4024));
+ AN2 U3836 ( .A(n4027), .B(n3320), .Z(n4018));
+ OR2 U3837 ( .A(n4028), .B(n3321), .Z(n4027));
+ AN2 U3838 ( .A(po040), .B(n4029), .Z(n4010));
+ OR2 U3839 ( .A(n4030), .B(n4031), .Z(n4029));
+ OR2 U3840 ( .A(n4032), .B(n4033), .Z(n4031));
+ AN2 U3841 ( .A(n4034), .B(n3261), .Z(n4032));
+ OR2 U3842 ( .A(n4035), .B(n4036), .Z(n4034));
+ OR2 U3843 ( .A(n4037), .B(n4038), .Z(n4036));
+ AN2 U3844 ( .A(n4039), .B(n3951), .Z(n4038));
+ AN2 U3845 ( .A(n4025), .B(n3314), .Z(n4039));
+ AN2 U3846 ( .A(n4040), .B(n4041), .Z(n4037));
+ AN2 U3847 ( .A(n4042), .B(n3320), .Z(n4035));
+ OR2 U3848 ( .A(n4043), .B(n4044), .Z(n4042));
+ AN2 U3849 ( .A(pi204), .B(n4045), .Z(n4044));
+ AN2 U3850 ( .A(n4046), .B(n4041), .Z(n4043));
+ OR2 U3851 ( .A(n4047), .B(n4048), .Z(n4030));
+ AN2 U3852 ( .A(n4049), .B(n4050), .Z(n4048));
+ OR2 U3853 ( .A(n4051), .B(n4052), .Z(n4050));
+ AN2 U3854 ( .A(n3321), .B(n3265), .Z(n4052));
+ AN2 U3855 ( .A(n3951), .B(n4053), .Z(n4051));
+ AN2 U3856 ( .A(n3326), .B(n3314), .Z(n4049));
+ AN2 U3857 ( .A(n4054), .B(n4055), .Z(n4047));
+ AN2 U3858 ( .A(n4056), .B(n4057), .Z(n4055));
+ AN2 U3859 ( .A(n3945), .B(pi204), .Z(n4054));
+ OR2 U3860 ( .A(n4058), .B(n4059), .Z(po073));
+ AN2 U3861 ( .A(n4060), .B(n4061), .Z(n4059));
+ AN2 U3862 ( .A(n3457), .B(n4062), .Z(n4058));
+ OR2 U3863 ( .A(n4063), .B(n4064), .Z(po068));
+ AN2 U3864 ( .A(n4065), .B(n4066), .Z(n4064));
+ OR2 U3865 ( .A(n4067), .B(n4068), .Z(n4065));
+ OR2 U3866 ( .A(n4069), .B(n4070), .Z(n4068));
+ AN2 U3867 ( .A(n4071), .B(n4072), .Z(n4070));
+ OR2 U3868 ( .A(n4073), .B(po059), .Z(n4071));
+ AN2 U3869 ( .A(n4074), .B(n2837), .Z(n4073));
+ AN2 U3870 ( .A(n4075), .B(n4076), .Z(n4069));
+ AN2 U3871 ( .A(n3780), .B(n4077), .Z(n4075));
+ AN2 U3872 ( .A(n4078), .B(n4079), .Z(n4063));
+ OR2 U3873 ( .A(n4080), .B(n4081), .Z(n4079));
+ OR2 U3874 ( .A(n4082), .B(n4083), .Z(n4081));
+ AN2 U3875 ( .A(n4084), .B(n2837), .Z(n4083));
+ AN2 U3876 ( .A(n4085), .B(pi192), .Z(n4082));
+ AN2 U3877 ( .A(n3778), .B(n3776), .Z(n4080));
+ OR2 U3878 ( .A(n4086), .B(n4087), .Z(n3776));
+ OR2 U3879 ( .A(n4088), .B(n4089), .Z(po061));
+ AN2 U3880 ( .A(n2861), .B(n4090), .Z(n4089));
+ OR2 U3881 ( .A(n4091), .B(n4092), .Z(n4090));
+ OR2 U3882 ( .A(n4093), .B(n4094), .Z(n4092));
+ AN2 U3883 ( .A(n4095), .B(n2901), .Z(n4094));
+ AN2 U3884 ( .A(n2862), .B(n2990), .Z(n4093));
+ OR2 U3885 ( .A(n4096), .B(n4097), .Z(n4091));
+ AN2 U3886 ( .A(n2880), .B(n4098), .Z(n4097));
+ AN2 U3887 ( .A(n4099), .B(n4100), .Z(n4096));
+ OR2 U3888 ( .A(n4101), .B(n4102), .Z(n4100));
+ OR2 U3889 ( .A(n2978), .B(n4103), .Z(n4102));
+ AN2 U3890 ( .A(n3222), .B(n2957), .Z(n4103));
+ AN2 U3891 ( .A(n2935), .B(po031), .Z(n4101));
+ IV2 U3892 ( .A(n2938), .Z(n2935));
+ AN2 U3893 ( .A(n4104), .B(n2998), .Z(n4088));
+ OR2 U3894 ( .A(n4105), .B(n4106), .Z(n4104));
+ OR2 U3895 ( .A(n4107), .B(n4108), .Z(n4106));
+ AN2 U3896 ( .A(n2892), .B(pi192), .Z(n4108));
+ AN2 U3897 ( .A(n2929), .B(n2837), .Z(n4107));
+ AN2 U3898 ( .A(n2930), .B(n3787), .Z(n4105));
+ OR2 U3899 ( .A(n4109), .B(n4110), .Z(n3787));
+ OR2 U3900 ( .A(n4111), .B(n4112), .Z(n4110));
+ AN2 U3901 ( .A(n4113), .B(n2837), .Z(n4112));
+ AN2 U3902 ( .A(n2876), .B(pi192), .Z(n4111));
+ AN2 U3903 ( .A(pi200), .B(n4114), .Z(n4109));
+ OR2 U3904 ( .A(n4115), .B(n2999), .Z(n4114));
+ OR2 U3905 ( .A(n4116), .B(n4117), .Z(n2999));
+ AN2 U3906 ( .A(n2938), .B(n2962), .Z(n4117));
+ AN2 U3907 ( .A(pi192), .B(n2878), .Z(n4116));
+ AN2 U3908 ( .A(n2918), .B(n2837), .Z(n4115));
+ AN2 U3909 ( .A(n2938), .B(pi082), .Z(n2918));
+ OR2 U3910 ( .A(n4118), .B(n4119), .Z(po060));
+ OR2 U3911 ( .A(n4120), .B(n4121), .Z(n4119));
+ AN2 U3912 ( .A(n4122), .B(n4123), .Z(n4121));
+ OR2 U3913 ( .A(n4124), .B(n4125), .Z(n4123));
+ AN2 U3914 ( .A(n4126), .B(n4127), .Z(n4124));
+ OR2 U3915 ( .A(n4128), .B(n4129), .Z(n4126));
+ AN2 U3916 ( .A(n4130), .B(n4131), .Z(n4122));
+ OR2 U3917 ( .A(n4132), .B(n4133), .Z(n4131));
+ AN2 U3918 ( .A(pi052), .B(n4134), .Z(n4132));
+ OR2 U3919 ( .A(po064), .B(n4135), .Z(n4130));
+ AN2 U3920 ( .A(n4136), .B(n4137), .Z(n4120));
+ OR2 U3921 ( .A(n4138), .B(n4139), .Z(n4137));
+ AN2 U3922 ( .A(n4140), .B(n4141), .Z(n4139));
+ OR2 U3923 ( .A(n4142), .B(n4143), .Z(n4140));
+ OR2 U3924 ( .A(n4144), .B(n4145), .Z(n4143));
+ AN2 U3925 ( .A(po040), .B(n3321), .Z(n4145));
+ AN2 U3926 ( .A(po103), .B(n4146), .Z(n4144));
+ OR2 U3927 ( .A(n4147), .B(n3321), .Z(n4146));
+ AN2 U3928 ( .A(n4148), .B(n4149), .Z(n4147));
+ OR2 U3929 ( .A(po004), .B(n4150), .Z(n4149));
+ OR2 U3930 ( .A(n4151), .B(n4152), .Z(n4142));
+ OR2 U3931 ( .A(n4153), .B(n4154), .Z(n4152));
+ IV2 U3932 ( .A(n4155), .Z(n4154));
+ OR2 U3933 ( .A(n4156), .B(n4157), .Z(n4155));
+ AN2 U3934 ( .A(n4158), .B(n4159), .Z(n4153));
+ AN2 U3935 ( .A(n4160), .B(po004), .Z(n4151));
+ AN2 U3936 ( .A(n3951), .B(po040), .Z(n4160));
+ AN2 U3937 ( .A(po004), .B(n4161), .Z(n4138));
+ AN2 U3938 ( .A(n4162), .B(n4163), .Z(n4136));
+ OR2 U3939 ( .A(n4164), .B(n4134), .Z(n4163));
+ AN2 U3940 ( .A(n4165), .B(po064), .Z(n4164));
+ IV2 U3941 ( .A(n4166), .Z(n4165));
+ OR2 U3942 ( .A(n4167), .B(n4125), .Z(n4166));
+ OR2 U3943 ( .A(n4135), .B(n4168), .Z(n4162));
+ OR2 U3944 ( .A(n4169), .B(n4170), .Z(n4168));
+ AN2 U3945 ( .A(pi054), .B(n4167), .Z(n4170));
+ AN2 U3946 ( .A(n4171), .B(n4133), .Z(n4169));
+ IV2 U3947 ( .A(n4172), .Z(n4171));
+ OR2 U3948 ( .A(n4173), .B(n4174), .Z(n4118));
+ AN2 U3949 ( .A(n4175), .B(pi054), .Z(n4174));
+ AN2 U3950 ( .A(n4176), .B(n4177), .Z(n4175));
+ OR2 U3951 ( .A(n4178), .B(n4179), .Z(n4176));
+ AN2 U3952 ( .A(n4134), .B(n4133), .Z(n4179));
+ AN2 U3953 ( .A(n4135), .B(po064), .Z(n4178));
+ AN2 U3954 ( .A(n4180), .B(n4135), .Z(n4173));
+ IV2 U3955 ( .A(n4134), .Z(n4135));
+ OR2 U3956 ( .A(n4181), .B(n4182), .Z(n4134));
+ AN2 U3957 ( .A(n4183), .B(n4184), .Z(n4182));
+ OR2 U3958 ( .A(n4185), .B(n4186), .Z(n4183));
+ AN2 U3959 ( .A(n4187), .B(n4188), .Z(n4186));
+ IV2 U3960 ( .A(n4189), .Z(n4188));
+ OR2 U3961 ( .A(n4190), .B(n4191), .Z(n4187));
+ AN2 U3962 ( .A(n4192), .B(n4193), .Z(n4191));
+ OR2 U3963 ( .A(n4194), .B(n4195), .Z(n4193));
+ AN2 U3964 ( .A(n4196), .B(n3261), .Z(n4195));
+ OR2 U3965 ( .A(n4197), .B(n4198), .Z(n4196));
+ AN2 U3966 ( .A(n4199), .B(po103), .Z(n4198));
+ AN2 U3967 ( .A(n4200), .B(n4201), .Z(n4199));
+ AN2 U3968 ( .A(n4202), .B(n4025), .Z(n4197));
+ AN2 U3969 ( .A(n4203), .B(po091), .Z(n4202));
+ AN2 U3970 ( .A(n4204), .B(n4205), .Z(n4190));
+ OR2 U3971 ( .A(n3317), .B(n4206), .Z(n4204));
+ OR2 U3972 ( .A(n4207), .B(n4208), .Z(n4206));
+ AN2 U3973 ( .A(n4209), .B(n3314), .Z(n4208));
+ IV2 U3974 ( .A(n4210), .Z(n4209));
+ AN2 U3975 ( .A(n4210), .B(n4057), .Z(n4207));
+ AN2 U3976 ( .A(po103), .B(n4148), .Z(n4210));
+ AN2 U3977 ( .A(n4189), .B(n4211), .Z(n4185));
+ OR2 U3978 ( .A(n4212), .B(n4213), .Z(n4211));
+ AN2 U3979 ( .A(n4214), .B(n4205), .Z(n4213));
+ OR2 U3980 ( .A(n3325), .B(n4215), .Z(n4214));
+ OR2 U3981 ( .A(n4216), .B(n3329), .Z(n4215));
+ AN2 U3982 ( .A(n4040), .B(n4217), .Z(n3329));
+ AN2 U3983 ( .A(n4192), .B(n4218), .Z(n4212));
+ OR2 U3984 ( .A(n4219), .B(n4220), .Z(n4218));
+ OR2 U3985 ( .A(n4221), .B(n4222), .Z(n4220));
+ AN2 U3986 ( .A(n4025), .B(n4201), .Z(n4222));
+ IV2 U3987 ( .A(n4223), .Z(n4025));
+ AN2 U3988 ( .A(po091), .B(n4200), .Z(n4221));
+ OR2 U3989 ( .A(n4224), .B(n4225), .Z(n4189));
+ AN2 U3990 ( .A(n4226), .B(n4227), .Z(n4225));
+ IV2 U3991 ( .A(n4228), .Z(n4224));
+ OR2 U3992 ( .A(n4227), .B(n4226), .Z(n4228));
+ AN2 U3993 ( .A(n4229), .B(n4230), .Z(n4181));
+ OR2 U3994 ( .A(n4231), .B(n4232), .Z(n4230));
+ OR2 U3995 ( .A(n4233), .B(n4234), .Z(n4232));
+ AN2 U3996 ( .A(n4235), .B(n4236), .Z(n4234));
+ OR2 U3997 ( .A(n4237), .B(n4238), .Z(n4235));
+ AN2 U3998 ( .A(n4239), .B(n4240), .Z(n4238));
+ OR2 U3999 ( .A(n3325), .B(n4216), .Z(n4240));
+ AN2 U4000 ( .A(po103), .B(n4194), .Z(n4216));
+ AN2 U4001 ( .A(n3265), .B(n4040), .Z(n3325));
+ AN2 U4002 ( .A(n4241), .B(n4242), .Z(n4237));
+ OR2 U4003 ( .A(n4243), .B(n4219), .Z(n4241));
+ OR2 U4004 ( .A(n4244), .B(n3321), .Z(n4219));
+ AN2 U4005 ( .A(n4203), .B(n4223), .Z(n4244));
+ AN2 U4006 ( .A(n4245), .B(n3314), .Z(n4243));
+ OR2 U4007 ( .A(n4246), .B(po091), .Z(n4245));
+ AN2 U4008 ( .A(n4247), .B(n3265), .Z(n4246));
+ AN2 U4009 ( .A(n4248), .B(n4249), .Z(n4233));
+ OR2 U4010 ( .A(n4250), .B(n4251), .Z(n4249));
+ OR2 U4011 ( .A(n4252), .B(n4253), .Z(n4251));
+ AN2 U4012 ( .A(po103), .B(n4254), .Z(n4253));
+ OR2 U4013 ( .A(n4255), .B(n3330), .Z(n4254));
+ AN2 U4014 ( .A(n3311), .B(n4242), .Z(n4255));
+ AN2 U4015 ( .A(n4194), .B(n3265), .Z(n4252));
+ AN2 U4016 ( .A(n4148), .B(n3311), .Z(n4194));
+ AN2 U4017 ( .A(n4239), .B(n4256), .Z(n4250));
+ OR2 U4018 ( .A(n4257), .B(n4258), .Z(n4256));
+ OR2 U4019 ( .A(n3926), .B(n4259), .Z(n4258));
+ AN2 U4020 ( .A(n4260), .B(n3314), .Z(n4259));
+ OR2 U4021 ( .A(n4261), .B(n4262), .Z(n4257));
+ AN2 U4022 ( .A(pi058), .B(pi129), .Z(n4262));
+ AN2 U4023 ( .A(n4056), .B(n3966), .Z(n4261));
+ AN2 U4024 ( .A(n4263), .B(n4264), .Z(n4231));
+ AN2 U4025 ( .A(n4265), .B(n4266), .Z(n4264));
+ OR2 U4026 ( .A(n4267), .B(n4236), .Z(n4266));
+ AN2 U4027 ( .A(n4268), .B(pi058), .Z(n4267));
+ AN2 U4028 ( .A(n4242), .B(n3265), .Z(n4268));
+ OR2 U4029 ( .A(n4269), .B(n4248), .Z(n4265));
+ IV2 U4030 ( .A(n4236), .Z(n4248));
+ AN2 U4031 ( .A(n4270), .B(n4271), .Z(n4236));
+ IV2 U4032 ( .A(n4272), .Z(n4271));
+ AN2 U4033 ( .A(n4226), .B(n4141), .Z(n4272));
+ OR2 U4034 ( .A(n4226), .B(n4141), .Z(n4270));
+ OR2 U4035 ( .A(n4273), .B(n4274), .Z(n4226));
+ IV2 U4036 ( .A(n4275), .Z(n4274));
+ OR2 U4037 ( .A(n4276), .B(n4277), .Z(n4275));
+ AN2 U4038 ( .A(n4277), .B(n4276), .Z(n4273));
+ AN2 U4039 ( .A(n4278), .B(n4279), .Z(n4276));
+ OR2 U4040 ( .A(n4280), .B(n4281), .Z(n4279));
+ IV2 U4041 ( .A(n4282), .Z(n4280));
+ OR2 U4042 ( .A(n4283), .B(n4282), .Z(n4278));
+ OR2 U4043 ( .A(n4284), .B(n4285), .Z(n4282));
+ AN2 U4044 ( .A(po040), .B(n4286), .Z(n4285));
+ OR2 U4045 ( .A(n4017), .B(n4287), .Z(n4286));
+ OR2 U4046 ( .A(n4288), .B(n4289), .Z(n4287));
+ AN2 U4047 ( .A(n4290), .B(n3314), .Z(n4289));
+ OR2 U4048 ( .A(n4291), .B(n3321), .Z(n4290));
+ IV2 U4049 ( .A(n4292), .Z(n4288));
+ OR2 U4050 ( .A(n4293), .B(n3314), .Z(n4292));
+ OR2 U4051 ( .A(n4294), .B(n3330), .Z(n4017));
+ AN2 U4052 ( .A(n4201), .B(n3926), .Z(n3330));
+ AN2 U4053 ( .A(n3311), .B(pi204), .Z(n4294));
+ AN2 U4054 ( .A(n4295), .B(n4013), .Z(n4284));
+ OR2 U4055 ( .A(n4033), .B(n4296), .Z(n4295));
+ OR2 U4056 ( .A(n4297), .B(n4298), .Z(n4296));
+ AN2 U4057 ( .A(n4299), .B(n3314), .Z(n4298));
+ AN2 U4058 ( .A(n4300), .B(n3261), .Z(n4299));
+ OR2 U4059 ( .A(n4301), .B(n4302), .Z(n4300));
+ AN2 U4060 ( .A(pi204), .B(n4203), .Z(n4302));
+ AN2 U4061 ( .A(po091), .B(n4041), .Z(n4301));
+ AN2 U4062 ( .A(n4040), .B(n4293), .Z(n4297));
+ AN2 U4063 ( .A(n3311), .B(n3951), .Z(n4033));
+ IV2 U4064 ( .A(n4260), .Z(n3311));
+ OR2 U4065 ( .A(n3321), .B(n4057), .Z(n4260));
+ IV2 U4066 ( .A(n4281), .Z(n4283));
+ OR2 U4067 ( .A(n4303), .B(n4304), .Z(n4281));
+ AN2 U4068 ( .A(n4305), .B(n4306), .Z(n4304));
+ AN2 U4069 ( .A(n4307), .B(n3261), .Z(n4305));
+ OR2 U4070 ( .A(n4308), .B(n4309), .Z(n4307));
+ AN2 U4071 ( .A(pi065), .B(n4148), .Z(n4309));
+ AN2 U4072 ( .A(n4310), .B(pi058), .Z(n4308));
+ AN2 U4073 ( .A(n4311), .B(n4312), .Z(n4303));
+ OR2 U4074 ( .A(n3961), .B(n4313), .Z(n4311));
+ IV2 U4075 ( .A(n3959), .Z(n3961));
+ OR2 U4076 ( .A(n4314), .B(n4315), .Z(n3959));
+ AN2 U4077 ( .A(pi058), .B(n4150), .Z(n4315));
+ AN2 U4078 ( .A(pi065), .B(n4316), .Z(n4314));
+ OR2 U4079 ( .A(n4317), .B(n4318), .Z(n4277));
+ AN2 U4080 ( .A(po004), .B(n3265), .Z(n4318));
+ AN2 U4081 ( .A(po103), .B(n4319), .Z(n4317));
+ AN2 U4082 ( .A(n4239), .B(pi058), .Z(n4269));
+ AN2 U4083 ( .A(n4040), .B(n3261), .Z(n4263));
+ AN2 U4084 ( .A(n4320), .B(n4167), .Z(n4180));
+ OR2 U4085 ( .A(n4129), .B(n4127), .Z(n4320));
+ AN2 U4086 ( .A(po023), .B(pi183), .Z(po058));
+ IV2 U4087 ( .A(n4321), .Z(po056));
+ AN2 U4088 ( .A(n4322), .B(n4323), .Z(n4321));
+ AN2 U4089 ( .A(pi063), .B(pi010), .Z(n4323));
+ AN2 U4090 ( .A(pi203), .B(pi073), .Z(n4322));
+ OR2 U4091 ( .A(n4324), .B(n4325), .Z(po055));
+ AN2 U4092 ( .A(n3015), .B(n4326), .Z(n4325));
+ AN2 U4093 ( .A(n3018), .B(n4327), .Z(n4324));
+ AN2 U4094 ( .A(n4328), .B(n4329), .Z(po053));
+ OR2 U4095 ( .A(n4306), .B(n4330), .Z(n4329));
+ IV2 U4096 ( .A(n4312), .Z(n4306));
+ OR2 U4097 ( .A(n4331), .B(n4312), .Z(n4328));
+ AN2 U4098 ( .A(n4332), .B(n3780), .Z(po051));
+ OR2 U4099 ( .A(n4333), .B(n4334), .Z(n4332));
+ OR2 U4100 ( .A(n4335), .B(n4336), .Z(po050));
+ AN2 U4101 ( .A(n4337), .B(n4338), .Z(n4336));
+ OR2 U4102 ( .A(n4339), .B(n4340), .Z(n4338));
+ AN2 U4103 ( .A(n4087), .B(n4341), .Z(n4339));
+ AN2 U4104 ( .A(n4342), .B(n4343), .Z(n4335));
+ OR2 U4105 ( .A(n4344), .B(n4345), .Z(n4343));
+ OR2 U4106 ( .A(n4346), .B(n4347), .Z(n4345));
+ AN2 U4107 ( .A(n4067), .B(n4348), .Z(n4346));
+ OR2 U4108 ( .A(n4349), .B(n4350), .Z(n4067));
+ AN2 U4109 ( .A(n4351), .B(pi192), .Z(n4350));
+ AN2 U4110 ( .A(n4072), .B(n3880), .Z(n4351));
+ AN2 U4111 ( .A(n4352), .B(n3890), .Z(n4349));
+ AN2 U4112 ( .A(n4353), .B(n3780), .Z(n4352));
+ OR2 U4113 ( .A(n4354), .B(n4355), .Z(n4344));
+ AN2 U4114 ( .A(n4356), .B(n3780), .Z(n4355));
+ AN2 U4115 ( .A(n4357), .B(n4076), .Z(n4354));
+ AN2 U4116 ( .A(n4072), .B(n4358), .Z(n4357));
+ OR2 U4117 ( .A(n4359), .B(n4360), .Z(po049));
+ AN2 U4118 ( .A(n3361), .B(n4361), .Z(n4360));
+ OR2 U4119 ( .A(n4362), .B(n4363), .Z(n4361));
+ AN2 U4120 ( .A(n4364), .B(n3451), .Z(n4362));
+ IV2 U4121 ( .A(n3401), .Z(n3361));
+ AN2 U4122 ( .A(n4365), .B(n3401), .Z(n4359));
+ OR2 U4123 ( .A(n4366), .B(n4367), .Z(n4365));
+ AN2 U4124 ( .A(n3453), .B(n4368), .Z(n4366));
+ OR2 U4125 ( .A(n4369), .B(n3253), .Z(po048));
+ AN2 U4126 ( .A(n4370), .B(n3255), .Z(n4369));
+ OR2 U4127 ( .A(n4371), .B(n4372), .Z(n4370));
+ AN2 U4128 ( .A(n4373), .B(n3259), .Z(n4371));
+ AN2 U4129 ( .A(n4374), .B(n4242), .Z(n4373));
+ OR2 U4130 ( .A(n4375), .B(n4376), .Z(po047));
+ OR2 U4131 ( .A(n4377), .B(n4378), .Z(n4376));
+ AN2 U4132 ( .A(n4379), .B(n4380), .Z(n4378));
+ AN2 U4133 ( .A(n4381), .B(n3259), .Z(n4377));
+ AN2 U4134 ( .A(n4382), .B(n4383), .Z(n4381));
+ OR2 U4135 ( .A(po004), .B(n4384), .Z(n4383));
+ OR2 U4136 ( .A(n3926), .B(n4385), .Z(n4384));
+ AN2 U4137 ( .A(n4386), .B(pi065), .Z(n4385));
+ AN2 U4138 ( .A(n4387), .B(n4157), .Z(n4386));
+ OR2 U4139 ( .A(n4319), .B(n4388), .Z(n4382));
+ OR2 U4140 ( .A(n4389), .B(n4390), .Z(n4388));
+ AN2 U4141 ( .A(n4391), .B(n3321), .Z(n4390));
+ AN2 U4142 ( .A(n4392), .B(n4310), .Z(n4389));
+ AN2 U4143 ( .A(pi204), .B(n4387), .Z(n4392));
+ OR2 U4144 ( .A(n4393), .B(n4394), .Z(n4375));
+ AN2 U4145 ( .A(n4395), .B(n4319), .Z(n4394));
+ OR2 U4146 ( .A(n4396), .B(n4397), .Z(n4395));
+ AN2 U4147 ( .A(n4227), .B(n4161), .Z(n4397));
+ AN2 U4148 ( .A(po004), .B(n4398), .Z(n4393));
+ OR2 U4149 ( .A(n4399), .B(n4400), .Z(n4398));
+ OR2 U4150 ( .A(n4401), .B(n4402), .Z(n4400));
+ AN2 U4151 ( .A(n4310), .B(n4403), .Z(n4402));
+ AN2 U4152 ( .A(n4404), .B(n4227), .Z(n4401));
+ AN2 U4153 ( .A(n4405), .B(n4406), .Z(n4399));
+ AN2 U4154 ( .A(n4407), .B(n3261), .Z(n4405));
+ OR2 U4155 ( .A(n4408), .B(n4409), .Z(n4407));
+ AN2 U4156 ( .A(n4028), .B(pi065), .Z(n4409));
+ AN2 U4157 ( .A(po040), .B(n4410), .Z(n4408));
+ OR2 U4158 ( .A(n4411), .B(n4412), .Z(n4410));
+ AN2 U4159 ( .A(pi065), .B(n4045), .Z(n4412));
+ AN2 U4160 ( .A(n4046), .B(n4156), .Z(n4411));
+ OR2 U4161 ( .A(n4413), .B(n4414), .Z(po046));
+ OR2 U4162 ( .A(n4415), .B(n4416), .Z(n4414));
+ AN2 U4163 ( .A(n3339), .B(n4417), .Z(n4416));
+ AN2 U4164 ( .A(n3341), .B(n4418), .Z(n4415));
+ OR2 U4165 ( .A(n4419), .B(n4420), .Z(n4413));
+ AN2 U4166 ( .A(n4421), .B(pi192), .Z(n4420));
+ OR2 U4167 ( .A(n4422), .B(n4423), .Z(n4421));
+ AN2 U4168 ( .A(n4424), .B(pi098), .Z(n4423));
+ AN2 U4169 ( .A(n4425), .B(n4426), .Z(n4424));
+ OR2 U4170 ( .A(n3242), .B(n3657), .Z(n4425));
+ IV2 U4171 ( .A(n3635), .Z(n3657));
+ AN2 U4172 ( .A(n4427), .B(n3638), .Z(n4422));
+ OR2 U4173 ( .A(n4428), .B(n4429), .Z(n4427));
+ AN2 U4174 ( .A(n4430), .B(pi171), .Z(n4429));
+ AN2 U4175 ( .A(n4431), .B(n4001), .Z(n4428));
+ AN2 U4176 ( .A(n4432), .B(n2837), .Z(n4419));
+ OR2 U4177 ( .A(n4433), .B(n4434), .Z(n4432));
+ AN2 U4178 ( .A(n4435), .B(pi003), .Z(n4434));
+ AN2 U4179 ( .A(n4436), .B(n4426), .Z(n4435));
+ OR2 U4180 ( .A(n3244), .B(n3616), .Z(n4436));
+ IV2 U4181 ( .A(n3593), .Z(n3616));
+ AN2 U4182 ( .A(n4437), .B(n3597), .Z(n4433));
+ OR2 U4183 ( .A(n4438), .B(n4439), .Z(n4437));
+ AN2 U4184 ( .A(n4430), .B(pi142), .Z(n4439));
+ AN2 U4185 ( .A(n4431), .B(n4440), .Z(n4438));
+ AN2 U4186 ( .A(n3236), .B(n4441), .Z(n4431));
+ OR2 U4187 ( .A(n4442), .B(n4443), .Z(po045));
+ AN2 U4188 ( .A(n4444), .B(n4445), .Z(n4443));
+ OR2 U4189 ( .A(n4446), .B(n3756), .Z(n4445));
+ AN2 U4190 ( .A(n4006), .B(n4005), .Z(n4446));
+ OR2 U4191 ( .A(n4447), .B(n4448), .Z(n4005));
+ AN2 U4192 ( .A(n4449), .B(n3301), .Z(n4447));
+ AN2 U4193 ( .A(n4450), .B(n3306), .Z(n4449));
+ AN2 U4194 ( .A(n3757), .B(n4451), .Z(n4442));
+ OR2 U4195 ( .A(n4452), .B(n4453), .Z(n4451));
+ OR2 U4196 ( .A(n4454), .B(n4455), .Z(n4453));
+ AN2 U4197 ( .A(po092), .B(n4456), .Z(n4455));
+ OR2 U4198 ( .A(n4008), .B(n4004), .Z(n4456));
+ AN2 U4199 ( .A(n4457), .B(n4458), .Z(n4008));
+ AN2 U4200 ( .A(n4458), .B(n4459), .Z(n4454));
+ OR2 U4201 ( .A(n4460), .B(n4461), .Z(n4459));
+ AN2 U4202 ( .A(n4462), .B(n4463), .Z(n4461));
+ AN2 U4203 ( .A(n4464), .B(n4465), .Z(n4462));
+ AN2 U4204 ( .A(n4466), .B(n4467), .Z(n4460));
+ AN2 U4205 ( .A(n4468), .B(n4469), .Z(n4466));
+ OR2 U4206 ( .A(n4470), .B(n4471), .Z(po043));
+ OR2 U4207 ( .A(n4472), .B(n4473), .Z(n4471));
+ AN2 U4208 ( .A(n4474), .B(n4475), .Z(n4473));
+ AN2 U4209 ( .A(n4476), .B(n4337), .Z(n4474));
+ AN2 U4210 ( .A(n4477), .B(n4478), .Z(n4472));
+ OR2 U4211 ( .A(n4479), .B(n4480), .Z(n4477));
+ AN2 U4212 ( .A(n4337), .B(n4481), .Z(n4480));
+ IV2 U4213 ( .A(n4342), .Z(n4337));
+ AN2 U4214 ( .A(n4342), .B(n4476), .Z(n4479));
+ IV2 U4215 ( .A(n4481), .Z(n4476));
+ AN2 U4216 ( .A(n4482), .B(n4481), .Z(n4470));
+ OR2 U4217 ( .A(n4483), .B(n4484), .Z(n4481));
+ OR2 U4218 ( .A(n4485), .B(n4486), .Z(n4484));
+ AN2 U4219 ( .A(n4487), .B(n4078), .Z(n4486));
+ OR2 U4220 ( .A(n4488), .B(n4489), .Z(n4487));
+ AN2 U4221 ( .A(n4490), .B(n3778), .Z(n4489));
+ AN2 U4222 ( .A(n3773), .B(n4491), .Z(n4488));
+ AN2 U4223 ( .A(n4492), .B(n4066), .Z(n4485));
+ AN2 U4224 ( .A(n4490), .B(n3773), .Z(n4492));
+ AN2 U4225 ( .A(n4491), .B(n4341), .Z(n4483));
+ IV2 U4226 ( .A(n4490), .Z(n4491));
+ OR2 U4227 ( .A(n4493), .B(n4494), .Z(n4490));
+ IV2 U4228 ( .A(n4495), .Z(n4494));
+ OR2 U4229 ( .A(n4496), .B(n4497), .Z(n4495));
+ AN2 U4230 ( .A(n4497), .B(n4496), .Z(n4493));
+ AN2 U4231 ( .A(n4498), .B(n4499), .Z(n4496));
+ IV2 U4232 ( .A(n4500), .Z(n4499));
+ AN2 U4233 ( .A(n4333), .B(n4501), .Z(n4500));
+ OR2 U4234 ( .A(n4501), .B(n4333), .Z(n4498));
+ OR2 U4235 ( .A(n4502), .B(n4503), .Z(n4501));
+ OR2 U4236 ( .A(n4504), .B(n4505), .Z(n4503));
+ OR2 U4237 ( .A(n4506), .B(n4507), .Z(n4505));
+ AN2 U4238 ( .A(n4508), .B(n4509), .Z(n4507));
+ AN2 U4239 ( .A(n4510), .B(n4511), .Z(n4506));
+ AN2 U4240 ( .A(n4512), .B(n4513), .Z(n4504));
+ OR2 U4241 ( .A(n4514), .B(n4515), .Z(n4502));
+ AN2 U4242 ( .A(n4516), .B(n4517), .Z(n4515));
+ AN2 U4243 ( .A(po102), .B(n4518), .Z(n4514));
+ OR2 U4244 ( .A(n4519), .B(n4520), .Z(n4518));
+ AN2 U4245 ( .A(n4513), .B(n4521), .Z(n4520));
+ OR2 U4246 ( .A(n4522), .B(n4523), .Z(n4513));
+ AN2 U4247 ( .A(n4508), .B(n3773), .Z(n4523));
+ AN2 U4248 ( .A(po025), .B(n4516), .Z(n4522));
+ AN2 U4249 ( .A(n4508), .B(n4524), .Z(n4519));
+ IV2 U4250 ( .A(n4510), .Z(n4508));
+ OR2 U4251 ( .A(n4525), .B(n4526), .Z(n4510));
+ AN2 U4252 ( .A(n4527), .B(n4528), .Z(n4526));
+ OR2 U4253 ( .A(n4529), .B(n4530), .Z(n4527));
+ OR2 U4254 ( .A(n4531), .B(n4532), .Z(n4530));
+ AN2 U4255 ( .A(po025), .B(n4533), .Z(n4532));
+ OR2 U4256 ( .A(n4534), .B(n4535), .Z(n4533));
+ OR2 U4257 ( .A(n4356), .B(n4536), .Z(n4535));
+ AN2 U4258 ( .A(n4537), .B(n4538), .Z(n4536));
+ AN2 U4259 ( .A(n4539), .B(n4540), .Z(n4537));
+ AN2 U4260 ( .A(n3890), .B(n4541), .Z(n4534));
+ OR2 U4261 ( .A(n4542), .B(n4543), .Z(n4541));
+ AN2 U4262 ( .A(n4085), .B(n4544), .Z(n4542));
+ AN2 U4263 ( .A(n3778), .B(n4545), .Z(n4531));
+ OR2 U4264 ( .A(n4546), .B(n4547), .Z(n4545));
+ OR2 U4265 ( .A(n4548), .B(n4549), .Z(n4547));
+ AN2 U4266 ( .A(n3775), .B(n4550), .Z(n4549));
+ AN2 U4267 ( .A(n4524), .B(n4333), .Z(n4548));
+ AN2 U4268 ( .A(n4086), .B(n4551), .Z(n4546));
+ OR2 U4269 ( .A(n4552), .B(n4553), .Z(n4529));
+ AN2 U4270 ( .A(n4554), .B(n4555), .Z(n4553));
+ OR2 U4271 ( .A(n4556), .B(n3888), .Z(n4555));
+ AN2 U4272 ( .A(pi192), .B(n4557), .Z(n4556));
+ AN2 U4273 ( .A(n4558), .B(n4559), .Z(n4554));
+ OR2 U4274 ( .A(n4085), .B(n4560), .Z(n4558));
+ AN2 U4275 ( .A(n4561), .B(n3773), .Z(n4560));
+ AN2 U4276 ( .A(n4562), .B(n4563), .Z(n4552));
+ OR2 U4277 ( .A(n4564), .B(n4565), .Z(n4563));
+ AN2 U4278 ( .A(n4566), .B(n4567), .Z(n4564));
+ AN2 U4279 ( .A(n3773), .B(n4076), .Z(n4566));
+ OR2 U4280 ( .A(pi076), .B(n4557), .Z(n4562));
+ AN2 U4281 ( .A(n4516), .B(n4568), .Z(n4525));
+ OR2 U4282 ( .A(n4569), .B(n4570), .Z(n4568));
+ OR2 U4283 ( .A(n4571), .B(n4572), .Z(n4570));
+ OR2 U4284 ( .A(n4573), .B(n4574), .Z(n4572));
+ AN2 U4285 ( .A(n4575), .B(n4576), .Z(n4574));
+ AN2 U4286 ( .A(n4577), .B(n4076), .Z(n4575));
+ AN2 U4287 ( .A(n3773), .B(n4578), .Z(n4577));
+ AN2 U4288 ( .A(n4579), .B(n4580), .Z(n4573));
+ OR2 U4289 ( .A(n4581), .B(n4565), .Z(n4579));
+ AN2 U4290 ( .A(n4539), .B(n4582), .Z(n4565));
+ AN2 U4291 ( .A(n2837), .B(n4550), .Z(n4582));
+ IV2 U4292 ( .A(n4540), .Z(n4550));
+ AN2 U4293 ( .A(n4567), .B(n4076), .Z(n4581));
+ AN2 U4294 ( .A(n4086), .B(n4583), .Z(n4571));
+ OR2 U4295 ( .A(n4584), .B(n4585), .Z(n4583));
+ AN2 U4296 ( .A(n4543), .B(n3773), .Z(n4585));
+ AN2 U4297 ( .A(n4586), .B(n4544), .Z(n4584));
+ OR2 U4298 ( .A(n4085), .B(n3778), .Z(n4586));
+ AN2 U4299 ( .A(n4557), .B(n3888), .Z(n4086));
+ OR2 U4300 ( .A(n4587), .B(n4588), .Z(n4569));
+ AN2 U4301 ( .A(n4589), .B(n4590), .Z(n4588));
+ OR2 U4302 ( .A(n4591), .B(n3890), .Z(n4590));
+ AN2 U4303 ( .A(po025), .B(pi192), .Z(n4591));
+ AN2 U4304 ( .A(n4559), .B(n4592), .Z(n4589));
+ OR2 U4305 ( .A(n4561), .B(n4085), .Z(n4592));
+ OR2 U4306 ( .A(n4551), .B(n4353), .Z(n4559));
+ AN2 U4307 ( .A(n4593), .B(n3775), .Z(n4587));
+ AN2 U4308 ( .A(n2837), .B(n4576), .Z(n3775));
+ AN2 U4309 ( .A(n4594), .B(n4540), .Z(n4593));
+ OR2 U4310 ( .A(n4567), .B(n4066), .Z(n4540));
+ OR2 U4311 ( .A(n4539), .B(n3778), .Z(n4594));
+ IV2 U4312 ( .A(n4528), .Z(n4516));
+ OR2 U4313 ( .A(n4595), .B(n4596), .Z(n4497));
+ AN2 U4314 ( .A(n4597), .B(n4598), .Z(n4596));
+ OR2 U4315 ( .A(n4599), .B(n4600), .Z(n4598));
+ AN2 U4316 ( .A(n4601), .B(n4602), .Z(n4600));
+ IV2 U4317 ( .A(n4603), .Z(n4599));
+ OR2 U4318 ( .A(n4602), .B(n4601), .Z(n4603));
+ OR2 U4319 ( .A(n4604), .B(n4605), .Z(n4601));
+ AN2 U4320 ( .A(n3295), .B(n4606), .Z(n4605));
+ AN2 U4321 ( .A(n4450), .B(n3301), .Z(n4604));
+ AN2 U4322 ( .A(n4607), .B(n4608), .Z(n4602));
+ OR2 U4323 ( .A(n4609), .B(n4610), .Z(n4608));
+ IV2 U4324 ( .A(n4611), .Z(n4610));
+ OR2 U4325 ( .A(n4611), .B(n4612), .Z(n4607));
+ IV2 U4326 ( .A(n4609), .Z(n4612));
+ OR2 U4327 ( .A(n4613), .B(n4614), .Z(n4609));
+ OR2 U4328 ( .A(n4615), .B(n4616), .Z(n4614));
+ AN2 U4329 ( .A(n4004), .B(n4617), .Z(n4616));
+ OR2 U4330 ( .A(n4618), .B(n4619), .Z(n4617));
+ AN2 U4331 ( .A(n4620), .B(n4463), .Z(n4619));
+ AN2 U4332 ( .A(n4621), .B(n4464), .Z(n4620));
+ AN2 U4333 ( .A(n4622), .B(n4467), .Z(n4618));
+ AN2 U4334 ( .A(n4623), .B(n4468), .Z(n4622));
+ AN2 U4335 ( .A(n4006), .B(n4624), .Z(n4615));
+ OR2 U4336 ( .A(n4625), .B(n4626), .Z(n4613));
+ AN2 U4337 ( .A(n4627), .B(n4628), .Z(n4626));
+ OR2 U4338 ( .A(n4629), .B(n4630), .Z(n4627));
+ AN2 U4339 ( .A(n4631), .B(pi192), .Z(n4630));
+ AN2 U4340 ( .A(n4632), .B(pi158), .Z(n4631));
+ AN2 U4341 ( .A(n4633), .B(n4634), .Z(n4632));
+ OR2 U4342 ( .A(n4635), .B(n4465), .Z(n4634));
+ OR2 U4343 ( .A(n4464), .B(n4636), .Z(n4633));
+ OR2 U4344 ( .A(n4621), .B(n3301), .Z(n4636));
+ AN2 U4345 ( .A(n4637), .B(n2837), .Z(n4629));
+ AN2 U4346 ( .A(n4638), .B(pi151), .Z(n4637));
+ AN2 U4347 ( .A(n4639), .B(n4640), .Z(n4638));
+ OR2 U4348 ( .A(n4641), .B(n4469), .Z(n4640));
+ OR2 U4349 ( .A(n4468), .B(n4642), .Z(n4639));
+ OR2 U4350 ( .A(n4623), .B(n3301), .Z(n4642));
+ AN2 U4351 ( .A(n4643), .B(po092), .Z(n4625));
+ AN2 U4352 ( .A(n4644), .B(n3295), .Z(n4643));
+ AN2 U4353 ( .A(n4645), .B(n4646), .Z(n4644));
+ OR2 U4354 ( .A(pi192), .B(n4647), .Z(n4646));
+ AN2 U4355 ( .A(n4641), .B(n4648), .Z(n4647));
+ OR2 U4356 ( .A(n2837), .B(n4649), .Z(n4645));
+ AN2 U4357 ( .A(n4635), .B(n3908), .Z(n4649));
+ IV2 U4358 ( .A(n3761), .Z(n4597));
+ AN2 U4359 ( .A(n4650), .B(n3761), .Z(n4595));
+ OR2 U4360 ( .A(n4651), .B(n4652), .Z(n3761));
+ AN2 U4361 ( .A(n4653), .B(n4654), .Z(n4651));
+ AN2 U4362 ( .A(n4333), .B(n4528), .Z(n4654));
+ OR2 U4363 ( .A(n4655), .B(n4656), .Z(n4528));
+ AN2 U4364 ( .A(n4657), .B(n3083), .Z(n4655));
+ AN2 U4365 ( .A(n3018), .B(n4658), .Z(n4657));
+ OR2 U4366 ( .A(n4659), .B(n4660), .Z(n4658));
+ OR2 U4367 ( .A(n4661), .B(n4662), .Z(n4660));
+ AN2 U4368 ( .A(n4663), .B(n3010), .Z(n4662));
+ AN2 U4369 ( .A(n4664), .B(n3049), .Z(n4661));
+ OR2 U4370 ( .A(n4665), .B(n4663), .Z(n4664));
+ AN2 U4371 ( .A(n4666), .B(n3010), .Z(n4665));
+ OR2 U4372 ( .A(n3100), .B(n4667), .Z(n4659));
+ AN2 U4373 ( .A(n4668), .B(n3012), .Z(n4667));
+ OR2 U4374 ( .A(n4669), .B(n4670), .Z(n4668));
+ AN2 U4375 ( .A(n4671), .B(pi201), .Z(n4670));
+ AN2 U4376 ( .A(n4672), .B(n3115), .Z(n4671));
+ OR2 U4377 ( .A(n4673), .B(n3173), .Z(n4672));
+ AN2 U4378 ( .A(n2837), .B(n3049), .Z(n4673));
+ AN2 U4379 ( .A(n4674), .B(pi088), .Z(n4669));
+ AN2 U4380 ( .A(n4675), .B(n3108), .Z(n4674));
+ OR2 U4381 ( .A(n4676), .B(n3064), .Z(n4675));
+ AN2 U4382 ( .A(pi192), .B(n3049), .Z(n4676));
+ AN2 U4383 ( .A(n4341), .B(n4482), .Z(n4653));
+ OR2 U4384 ( .A(n4677), .B(n4678), .Z(n4650));
+ OR2 U4385 ( .A(n4679), .B(n4680), .Z(n4678));
+ OR2 U4386 ( .A(n4681), .B(n4682), .Z(n4680));
+ AN2 U4387 ( .A(n4683), .B(n4684), .Z(n4682));
+ AN2 U4388 ( .A(n4685), .B(n4648), .Z(n4683));
+ AN2 U4389 ( .A(n4686), .B(n4687), .Z(n4681));
+ OR2 U4390 ( .A(n4688), .B(n4689), .Z(n4687));
+ OR2 U4391 ( .A(n4690), .B(n4691), .Z(n4689));
+ AN2 U4392 ( .A(n4692), .B(n4621), .Z(n4691));
+ AN2 U4393 ( .A(n4685), .B(n4623), .Z(n4690));
+ AN2 U4394 ( .A(n4693), .B(n3300), .Z(n4688));
+ IV2 U4395 ( .A(n4684), .Z(n4686));
+ OR2 U4396 ( .A(n4694), .B(n4695), .Z(n4679));
+ AN2 U4397 ( .A(n4696), .B(n3300), .Z(n4695));
+ AN2 U4398 ( .A(po014), .B(n4684), .Z(n4696));
+ OR2 U4399 ( .A(n4697), .B(n4698), .Z(n4684));
+ AN2 U4400 ( .A(n4699), .B(n4450), .Z(n4697));
+ AN2 U4401 ( .A(po039), .B(n4700), .Z(n4694));
+ OR2 U4402 ( .A(n4701), .B(n4702), .Z(n4700));
+ AN2 U4403 ( .A(n4698), .B(n4703), .Z(n4702));
+ AN2 U4404 ( .A(n4704), .B(n4606), .Z(n4698));
+ AN2 U4405 ( .A(n4705), .B(n4706), .Z(n4701));
+ AN2 U4406 ( .A(n4707), .B(n4708), .Z(n4705));
+ OR2 U4407 ( .A(n4704), .B(n3295), .Z(n4708));
+ OR2 U4408 ( .A(n4699), .B(n3301), .Z(n4707));
+ OR2 U4409 ( .A(n4709), .B(n4710), .Z(n4677));
+ AN2 U4410 ( .A(n4711), .B(n4699), .Z(n4710));
+ IV2 U4411 ( .A(n4704), .Z(n4699));
+ AN2 U4412 ( .A(n4450), .B(n4712), .Z(n4711));
+ OR2 U4413 ( .A(po014), .B(n3301), .Z(n4712));
+ AN2 U4414 ( .A(n4713), .B(n4704), .Z(n4709));
+ OR2 U4415 ( .A(n4714), .B(n4715), .Z(n4704));
+ OR2 U4416 ( .A(n4716), .B(n4717), .Z(n4715));
+ OR2 U4417 ( .A(n4718), .B(n4719), .Z(n4717));
+ IV2 U4418 ( .A(n4720), .Z(n4719));
+ OR2 U4419 ( .A(n4721), .B(n4006), .Z(n4720));
+ OR2 U4420 ( .A(n4444), .B(n3756), .Z(n4721));
+ AN2 U4421 ( .A(n4722), .B(n4006), .Z(n4718));
+ AN2 U4422 ( .A(n4444), .B(n4452), .Z(n4722));
+ OR2 U4423 ( .A(n4723), .B(n4724), .Z(n4452));
+ OR2 U4424 ( .A(n4725), .B(n4726), .Z(n4724));
+ AN2 U4425 ( .A(po092), .B(n4009), .Z(n4726));
+ OR2 U4426 ( .A(n4727), .B(n4728), .Z(n4009));
+ AN2 U4427 ( .A(n3295), .B(n4729), .Z(n4728));
+ AN2 U4428 ( .A(n4606), .B(n4457), .Z(n4727));
+ OR2 U4429 ( .A(n4730), .B(n4706), .Z(n4457));
+ OR2 U4430 ( .A(n4731), .B(n4732), .Z(n4706));
+ AN2 U4431 ( .A(n4733), .B(pi192), .Z(n4732));
+ AN2 U4432 ( .A(n4465), .B(n3870), .Z(n4733));
+ AN2 U4433 ( .A(n4734), .B(n2837), .Z(n4731));
+ AN2 U4434 ( .A(n4469), .B(n4735), .Z(n4734));
+ AN2 U4435 ( .A(po039), .B(n4729), .Z(n4730));
+ OR2 U4436 ( .A(po014), .B(n4736), .Z(n4729));
+ AN2 U4437 ( .A(n4737), .B(n4606), .Z(n4725));
+ AN2 U4438 ( .A(po014), .B(n4738), .Z(n4737));
+ OR2 U4439 ( .A(n4739), .B(n4740), .Z(n4738));
+ AN2 U4440 ( .A(n4463), .B(n4464), .Z(n4740));
+ AN2 U4441 ( .A(n4467), .B(n4468), .Z(n4739));
+ OR2 U4442 ( .A(n4741), .B(n4742), .Z(n4723));
+ AN2 U4443 ( .A(n4743), .B(n4463), .Z(n4742));
+ AN2 U4444 ( .A(n3909), .B(pi192), .Z(n4463));
+ IV2 U4445 ( .A(pi158), .Z(n3909));
+ AN2 U4446 ( .A(n4744), .B(n3908), .Z(n4743));
+ OR2 U4447 ( .A(n4745), .B(n3295), .Z(n4744));
+ AN2 U4448 ( .A(n4606), .B(n4464), .Z(n4745));
+ AN2 U4449 ( .A(n4746), .B(n4467), .Z(n4741));
+ AN2 U4450 ( .A(n2837), .B(n4747), .Z(n4467));
+ AN2 U4451 ( .A(n4748), .B(n4648), .Z(n4746));
+ OR2 U4452 ( .A(n4749), .B(n3295), .Z(n4748));
+ AN2 U4453 ( .A(n4606), .B(n4468), .Z(n4749));
+ AN2 U4454 ( .A(n3756), .B(n4611), .Z(n4716));
+ OR2 U4455 ( .A(n4750), .B(n4751), .Z(n4611));
+ AN2 U4456 ( .A(n4004), .B(n4444), .Z(n4750));
+ IV2 U4457 ( .A(n4006), .Z(n4004));
+ AN2 U4458 ( .A(n4628), .B(n4752), .Z(n3756));
+ OR2 U4459 ( .A(n3758), .B(n3760), .Z(n4714));
+ AN2 U4460 ( .A(n4448), .B(n4751), .Z(n3758));
+ OR2 U4461 ( .A(n4713), .B(n4693), .Z(n4448));
+ OR2 U4462 ( .A(n4753), .B(n4754), .Z(n4693));
+ AN2 U4463 ( .A(n4621), .B(pi192), .Z(n4754));
+ AN2 U4464 ( .A(n4623), .B(n2837), .Z(n4753));
+ AN2 U4465 ( .A(n3301), .B(n4624), .Z(n4713));
+ OR2 U4466 ( .A(n4755), .B(n4756), .Z(po042));
+ AN2 U4467 ( .A(n4757), .B(n2837), .Z(n4756));
+ OR2 U4468 ( .A(n4758), .B(n4759), .Z(n4757));
+ OR2 U4469 ( .A(n4760), .B(n4761), .Z(n4759));
+ AN2 U4470 ( .A(n4762), .B(n4763), .Z(n4761));
+ OR2 U4471 ( .A(n4764), .B(n4765), .Z(n4763));
+ IV2 U4472 ( .A(n4766), .Z(n4762));
+ AN2 U4473 ( .A(n4765), .B(n4764), .Z(n4766));
+ OR2 U4474 ( .A(n4767), .B(n4768), .Z(n4764));
+ AN2 U4475 ( .A(n4769), .B(n4770), .Z(n4768));
+ AN2 U4476 ( .A(n4771), .B(pi028), .Z(n4767));
+ AN2 U4477 ( .A(n4772), .B(n4773), .Z(n4765));
+ OR2 U4478 ( .A(n4774), .B(pi094), .Z(n4773));
+ IV2 U4479 ( .A(n4775), .Z(n4772));
+ AN2 U4480 ( .A(n4774), .B(pi094), .Z(n4775));
+ AN2 U4481 ( .A(n4776), .B(n4777), .Z(n4774));
+ OR2 U4482 ( .A(n4778), .B(pi173), .Z(n4777));
+ OR2 U4483 ( .A(n4779), .B(pi163), .Z(n4776));
+ IV2 U4484 ( .A(pi173), .Z(n4779));
+ AN2 U4485 ( .A(n4780), .B(n4781), .Z(n4760));
+ IV2 U4486 ( .A(n4782), .Z(n4781));
+ AN2 U4487 ( .A(n4783), .B(n4784), .Z(n4782));
+ OR2 U4488 ( .A(n4784), .B(n4783), .Z(n4780));
+ AN2 U4489 ( .A(n4785), .B(n4786), .Z(n4783));
+ IV2 U4490 ( .A(n4787), .Z(n4786));
+ AN2 U4491 ( .A(n4788), .B(n4789), .Z(n4787));
+ OR2 U4492 ( .A(n4789), .B(n4788), .Z(n4785));
+ OR2 U4493 ( .A(n4790), .B(n4791), .Z(n4788));
+ AN2 U4494 ( .A(pi025), .B(n4792), .Z(n4791));
+ IV2 U4495 ( .A(n4793), .Z(n4790));
+ OR2 U4496 ( .A(n4792), .B(pi025), .Z(n4793));
+ IV2 U4497 ( .A(pi035), .Z(n4792));
+ AN2 U4498 ( .A(n4794), .B(n4795), .Z(n4789));
+ IV2 U4499 ( .A(n4796), .Z(n4795));
+ AN2 U4500 ( .A(pi056), .B(n4797), .Z(n4796));
+ OR2 U4501 ( .A(n4797), .B(pi056), .Z(n4794));
+ IV2 U4502 ( .A(pi100), .Z(n4797));
+ OR2 U4503 ( .A(n4798), .B(n4799), .Z(n4784));
+ IV2 U4504 ( .A(n4800), .Z(n4799));
+ OR2 U4505 ( .A(n4801), .B(n4802), .Z(n4800));
+ AN2 U4506 ( .A(n4802), .B(n4801), .Z(n4798));
+ AN2 U4507 ( .A(n4803), .B(n4804), .Z(n4801));
+ IV2 U4508 ( .A(n4805), .Z(n4804));
+ AN2 U4509 ( .A(pi126), .B(n4806), .Z(n4805));
+ OR2 U4510 ( .A(n4806), .B(pi126), .Z(n4803));
+ IV2 U4511 ( .A(pi146), .Z(n4806));
+ OR2 U4512 ( .A(n4807), .B(n4808), .Z(n4802));
+ AN2 U4513 ( .A(pi190), .B(n4809), .Z(n4808));
+ IV2 U4514 ( .A(pi202), .Z(n4809));
+ AN2 U4515 ( .A(pi202), .B(n4810), .Z(n4807));
+ IV2 U4516 ( .A(pi190), .Z(n4810));
+ OR2 U4517 ( .A(n4811), .B(n4812), .Z(n4758));
+ AN2 U4518 ( .A(n4813), .B(n4814), .Z(n4812));
+ IV2 U4519 ( .A(n4815), .Z(n4814));
+ AN2 U4520 ( .A(n4816), .B(n4817), .Z(n4815));
+ OR2 U4521 ( .A(n4817), .B(n4816), .Z(n4813));
+ AN2 U4522 ( .A(n4818), .B(n4819), .Z(n4816));
+ OR2 U4523 ( .A(n4820), .B(pi019), .Z(n4819));
+ OR2 U4524 ( .A(n4821), .B(n4822), .Z(n4818));
+ IV2 U4525 ( .A(pi019), .Z(n4822));
+ OR2 U4526 ( .A(n4823), .B(n4824), .Z(n4817));
+ IV2 U4527 ( .A(n4825), .Z(n4824));
+ OR2 U4528 ( .A(n4826), .B(pi085), .Z(n4825));
+ AN2 U4529 ( .A(n4826), .B(pi085), .Z(n4823));
+ AN2 U4530 ( .A(n4827), .B(n4828), .Z(n4826));
+ OR2 U4531 ( .A(n4829), .B(pi167), .Z(n4828));
+ IV2 U4532 ( .A(pi110), .Z(n4829));
+ OR2 U4533 ( .A(n4830), .B(pi110), .Z(n4827));
+ IV2 U4534 ( .A(pi167), .Z(n4830));
+ AN2 U4535 ( .A(n4831), .B(n4832), .Z(n4811));
+ IV2 U4536 ( .A(n4833), .Z(n4832));
+ AN2 U4537 ( .A(n4834), .B(n4835), .Z(n4833));
+ OR2 U4538 ( .A(n4835), .B(n4834), .Z(n4831));
+ AN2 U4539 ( .A(n4836), .B(n4837), .Z(n4834));
+ OR2 U4540 ( .A(n4838), .B(pi020), .Z(n4837));
+ OR2 U4541 ( .A(n4839), .B(n4840), .Z(n4836));
+ IV2 U4542 ( .A(pi020), .Z(n4840));
+ OR2 U4543 ( .A(n4841), .B(n4842), .Z(n4835));
+ IV2 U4544 ( .A(n4843), .Z(n4842));
+ OR2 U4545 ( .A(n4844), .B(pi047), .Z(n4843));
+ AN2 U4546 ( .A(n4844), .B(pi047), .Z(n4841));
+ AN2 U4547 ( .A(n4845), .B(n4846), .Z(n4844));
+ OR2 U4548 ( .A(n4847), .B(pi153), .Z(n4846));
+ IV2 U4549 ( .A(pi075), .Z(n4847));
+ OR2 U4550 ( .A(n4848), .B(pi075), .Z(n4845));
+ IV2 U4551 ( .A(pi153), .Z(n4848));
+ AN2 U4552 ( .A(pi192), .B(n4849), .Z(n4755));
+ OR2 U4553 ( .A(n4850), .B(n4851), .Z(n4849));
+ OR2 U4554 ( .A(n4852), .B(n4853), .Z(n4851));
+ AN2 U4555 ( .A(n4854), .B(n4855), .Z(n4853));
+ OR2 U4556 ( .A(n4856), .B(n4857), .Z(n4855));
+ IV2 U4557 ( .A(n4858), .Z(n4854));
+ AN2 U4558 ( .A(n4857), .B(n4856), .Z(n4858));
+ OR2 U4559 ( .A(n4859), .B(n4860), .Z(n4856));
+ AN2 U4560 ( .A(n4839), .B(n4861), .Z(n4860));
+ AN2 U4561 ( .A(n4838), .B(po014), .Z(n4859));
+ IV2 U4562 ( .A(n4839), .Z(n4838));
+ OR2 U4563 ( .A(n4862), .B(n4863), .Z(n4839));
+ AN2 U4564 ( .A(n4864), .B(pi192), .Z(n4863));
+ OR2 U4565 ( .A(n4865), .B(n4866), .Z(n4864));
+ IV2 U4566 ( .A(n4867), .Z(n4866));
+ OR2 U4567 ( .A(n4868), .B(n4869), .Z(n4867));
+ AN2 U4568 ( .A(n4869), .B(n4868), .Z(n4865));
+ AN2 U4569 ( .A(n4870), .B(n4871), .Z(n4868));
+ OR2 U4570 ( .A(n4872), .B(po024), .Z(n4871));
+ IV2 U4571 ( .A(n4873), .Z(n4872));
+ OR2 U4572 ( .A(n4873), .B(n4874), .Z(n4870));
+ OR2 U4573 ( .A(n4875), .B(n4876), .Z(n4873));
+ AN2 U4574 ( .A(po025), .B(n4877), .Z(n4876));
+ AN2 U4575 ( .A(po059), .B(n4557), .Z(n4875));
+ OR2 U4576 ( .A(n4878), .B(n4879), .Z(n4869));
+ AN2 U4577 ( .A(n4880), .B(n4881), .Z(n4879));
+ AN2 U4578 ( .A(n4882), .B(po072), .Z(n4878));
+ IV2 U4579 ( .A(n4880), .Z(n4882));
+ OR2 U4580 ( .A(n4883), .B(n4884), .Z(n4880));
+ AN2 U4581 ( .A(po084), .B(n4885), .Z(n4884));
+ AN2 U4582 ( .A(po102), .B(n4886), .Z(n4883));
+ IV2 U4583 ( .A(po084), .Z(n4886));
+ AN2 U4584 ( .A(n4887), .B(n2837), .Z(n4862));
+ OR2 U4585 ( .A(n4888), .B(n4889), .Z(n4887));
+ AN2 U4586 ( .A(n4890), .B(n4891), .Z(n4889));
+ IV2 U4587 ( .A(n4892), .Z(n4888));
+ OR2 U4588 ( .A(n4891), .B(n4890), .Z(n4892));
+ OR2 U4589 ( .A(n4893), .B(n4894), .Z(n4890));
+ IV2 U4590 ( .A(n4895), .Z(n4894));
+ OR2 U4591 ( .A(n4896), .B(pi014), .Z(n4895));
+ AN2 U4592 ( .A(n4896), .B(pi014), .Z(n4893));
+ AN2 U4593 ( .A(n4897), .B(n4898), .Z(n4896));
+ OR2 U4594 ( .A(n4899), .B(pi111), .Z(n4898));
+ OR2 U4595 ( .A(n4900), .B(pi097), .Z(n4897));
+ IV2 U4596 ( .A(pi111), .Z(n4900));
+ AN2 U4597 ( .A(n4901), .B(n4902), .Z(n4891));
+ OR2 U4598 ( .A(n4903), .B(pi143), .Z(n4902));
+ IV2 U4599 ( .A(n4904), .Z(n4901));
+ AN2 U4600 ( .A(n4903), .B(pi143), .Z(n4904));
+ AN2 U4601 ( .A(n4905), .B(n4906), .Z(n4903));
+ OR2 U4602 ( .A(n4907), .B(pi189), .Z(n4906));
+ IV2 U4603 ( .A(n4908), .Z(n4905));
+ AN2 U4604 ( .A(pi189), .B(n4907), .Z(n4908));
+ IV2 U4605 ( .A(pi176), .Z(n4907));
+ AN2 U4606 ( .A(n4909), .B(n4910), .Z(n4857));
+ OR2 U4607 ( .A(n4911), .B(po039), .Z(n4910));
+ IV2 U4608 ( .A(n4912), .Z(n4911));
+ OR2 U4609 ( .A(n4912), .B(n3300), .Z(n4909));
+ OR2 U4610 ( .A(n4913), .B(n4914), .Z(n4912));
+ AN2 U4611 ( .A(po063), .B(n4628), .Z(n4914));
+ AN2 U4612 ( .A(po092), .B(n4915), .Z(n4913));
+ AN2 U4613 ( .A(n4916), .B(n4917), .Z(n4852));
+ IV2 U4614 ( .A(n4918), .Z(n4917));
+ AN2 U4615 ( .A(n4919), .B(n4920), .Z(n4918));
+ OR2 U4616 ( .A(n4920), .B(n4919), .Z(n4916));
+ IV2 U4617 ( .A(n4921), .Z(n4919));
+ OR2 U4618 ( .A(n4922), .B(n4923), .Z(n4921));
+ AN2 U4619 ( .A(n4821), .B(n3391), .Z(n4923));
+ IV2 U4620 ( .A(n4924), .Z(n3391));
+ AN2 U4621 ( .A(n4924), .B(n4820), .Z(n4922));
+ IV2 U4622 ( .A(n4821), .Z(n4820));
+ OR2 U4623 ( .A(n4925), .B(n4926), .Z(n4821));
+ AN2 U4624 ( .A(n4927), .B(pi192), .Z(n4926));
+ OR2 U4625 ( .A(n4928), .B(n4929), .Z(n4927));
+ IV2 U4626 ( .A(n4930), .Z(n4929));
+ OR2 U4627 ( .A(n4931), .B(n4932), .Z(n4930));
+ AN2 U4628 ( .A(n4932), .B(n4931), .Z(n4928));
+ AN2 U4629 ( .A(n4933), .B(n4934), .Z(n4931));
+ OR2 U4630 ( .A(n4935), .B(po001), .Z(n4934));
+ IV2 U4631 ( .A(n4936), .Z(n4935));
+ OR2 U4632 ( .A(n4936), .B(n4937), .Z(n4933));
+ OR2 U4633 ( .A(n4938), .B(n4939), .Z(n4936));
+ AN2 U4634 ( .A(po011), .B(n4441), .Z(n4939));
+ AN2 U4635 ( .A(po036), .B(n3688), .Z(n4938));
+ OR2 U4636 ( .A(n4940), .B(n4941), .Z(n4932));
+ AN2 U4637 ( .A(n4942), .B(n4943), .Z(n4941));
+ AN2 U4638 ( .A(n4944), .B(po057), .Z(n4940));
+ IV2 U4639 ( .A(n4942), .Z(n4944));
+ OR2 U4640 ( .A(n4945), .B(n4946), .Z(n4942));
+ AN2 U4641 ( .A(po069), .B(n4947), .Z(n4946));
+ AN2 U4642 ( .A(po082), .B(n4948), .Z(n4945));
+ IV2 U4643 ( .A(po069), .Z(n4948));
+ AN2 U4644 ( .A(n4949), .B(n2837), .Z(n4925));
+ OR2 U4645 ( .A(n4950), .B(n4951), .Z(n4949));
+ AN2 U4646 ( .A(n4952), .B(n4953), .Z(n4951));
+ IV2 U4647 ( .A(n4954), .Z(n4950));
+ OR2 U4648 ( .A(n4953), .B(n4952), .Z(n4954));
+ OR2 U4649 ( .A(n4955), .B(n4956), .Z(n4952));
+ IV2 U4650 ( .A(n4957), .Z(n4956));
+ OR2 U4651 ( .A(n4958), .B(pi024), .Z(n4957));
+ AN2 U4652 ( .A(n4958), .B(pi024), .Z(n4955));
+ AN2 U4653 ( .A(n4959), .B(n4960), .Z(n4958));
+ OR2 U4654 ( .A(n4961), .B(pi078), .Z(n4960));
+ OR2 U4655 ( .A(n4962), .B(pi030), .Z(n4959));
+ IV2 U4656 ( .A(pi078), .Z(n4962));
+ AN2 U4657 ( .A(n4963), .B(n4964), .Z(n4953));
+ OR2 U4658 ( .A(n4965), .B(pi087), .Z(n4964));
+ IV2 U4659 ( .A(n4966), .Z(n4963));
+ AN2 U4660 ( .A(n4965), .B(pi087), .Z(n4966));
+ AN2 U4661 ( .A(n4967), .B(n4968), .Z(n4965));
+ OR2 U4662 ( .A(n4969), .B(pi164), .Z(n4968));
+ OR2 U4663 ( .A(n4970), .B(pi159), .Z(n4967));
+ IV2 U4664 ( .A(pi164), .Z(n4970));
+ OR2 U4665 ( .A(n4971), .B(n4972), .Z(n4924));
+ AN2 U4666 ( .A(po027), .B(n3512), .Z(n4972));
+ AN2 U4667 ( .A(po104), .B(n3363), .Z(n4971));
+ OR2 U4668 ( .A(n4973), .B(n4974), .Z(n4920));
+ AN2 U4669 ( .A(po038), .B(n3380), .Z(n4974));
+ AN2 U4670 ( .A(po071), .B(n4975), .Z(n4973));
+ OR2 U4671 ( .A(n4976), .B(n4977), .Z(n4850));
+ AN2 U4672 ( .A(n4978), .B(n4979), .Z(n4977));
+ OR2 U4673 ( .A(n4980), .B(n4981), .Z(n4979));
+ IV2 U4674 ( .A(n4982), .Z(n4978));
+ AN2 U4675 ( .A(n4981), .B(n4980), .Z(n4982));
+ OR2 U4676 ( .A(n4983), .B(n4984), .Z(n4980));
+ AN2 U4677 ( .A(n4769), .B(n3049), .Z(n4984));
+ AN2 U4678 ( .A(n4771), .B(po010), .Z(n4983));
+ IV2 U4679 ( .A(n4769), .Z(n4771));
+ OR2 U4680 ( .A(n4985), .B(n4986), .Z(n4769));
+ AN2 U4681 ( .A(n4987), .B(pi192), .Z(n4986));
+ OR2 U4682 ( .A(n4988), .B(n4989), .Z(n4987));
+ IV2 U4683 ( .A(n4990), .Z(n4989));
+ OR2 U4684 ( .A(n4991), .B(n4992), .Z(n4990));
+ AN2 U4685 ( .A(n4992), .B(n4991), .Z(n4988));
+ AN2 U4686 ( .A(n4993), .B(n4994), .Z(n4991));
+ OR2 U4687 ( .A(n4995), .B(po031), .Z(n4994));
+ IV2 U4688 ( .A(n4996), .Z(n4995));
+ OR2 U4689 ( .A(n4996), .B(n2962), .Z(n4993));
+ OR2 U4690 ( .A(n4997), .B(n4998), .Z(n4996));
+ AN2 U4691 ( .A(po044), .B(n4999), .Z(n4998));
+ IV2 U4692 ( .A(po052), .Z(n4999));
+ AN2 U4693 ( .A(po052), .B(n5000), .Z(n4997));
+ OR2 U4694 ( .A(n5001), .B(n5002), .Z(n4992));
+ AN2 U4695 ( .A(n5003), .B(n5004), .Z(n5002));
+ AN2 U4696 ( .A(n5005), .B(po079), .Z(n5001));
+ IV2 U4697 ( .A(n5003), .Z(n5005));
+ OR2 U4698 ( .A(n5006), .B(n5007), .Z(n5003));
+ AN2 U4699 ( .A(po106), .B(n2931), .Z(n5007));
+ AN2 U4700 ( .A(po107), .B(n5008), .Z(n5006));
+ AN2 U4701 ( .A(n5009), .B(n2837), .Z(n4985));
+ OR2 U4702 ( .A(n5010), .B(n5011), .Z(n5009));
+ IV2 U4703 ( .A(n5012), .Z(n5011));
+ OR2 U4704 ( .A(n5013), .B(n5014), .Z(n5012));
+ AN2 U4705 ( .A(n5014), .B(n5013), .Z(n5010));
+ AN2 U4706 ( .A(n5015), .B(n5016), .Z(n5013));
+ OR2 U4707 ( .A(n5017), .B(pi011), .Z(n5016));
+ IV2 U4708 ( .A(n5018), .Z(n5017));
+ OR2 U4709 ( .A(n5018), .B(n5019), .Z(n5015));
+ OR2 U4710 ( .A(n5020), .B(n5021), .Z(n5018));
+ AN2 U4711 ( .A(pi021), .B(n5022), .Z(n5021));
+ AN2 U4712 ( .A(pi032), .B(n5023), .Z(n5020));
+ IV2 U4713 ( .A(pi021), .Z(n5023));
+ OR2 U4714 ( .A(n5024), .B(n5025), .Z(n5014));
+ AN2 U4715 ( .A(n5026), .B(n5027), .Z(n5025));
+ AN2 U4716 ( .A(n5028), .B(pi086), .Z(n5024));
+ IV2 U4717 ( .A(n5026), .Z(n5028));
+ OR2 U4718 ( .A(n5029), .B(n5030), .Z(n5026));
+ AN2 U4719 ( .A(pi115), .B(n5031), .Z(n5030));
+ AN2 U4720 ( .A(pi165), .B(n5032), .Z(n5029));
+ IV2 U4721 ( .A(pi115), .Z(n5032));
+ AN2 U4722 ( .A(n5033), .B(n5034), .Z(n4981));
+ OR2 U4723 ( .A(n5035), .B(po035), .Z(n5034));
+ IV2 U4724 ( .A(n5036), .Z(n5035));
+ OR2 U4725 ( .A(n5036), .B(n5037), .Z(n5033));
+ OR2 U4726 ( .A(n5038), .B(n5039), .Z(n5036));
+ AN2 U4727 ( .A(po070), .B(n3286), .Z(n5039));
+ AN2 U4728 ( .A(po099), .B(n5040), .Z(n5038));
+ AN2 U4729 ( .A(n5041), .B(n5042), .Z(n4976));
+ OR2 U4730 ( .A(n5043), .B(n5044), .Z(n5042));
+ IV2 U4731 ( .A(n5045), .Z(n5041));
+ AN2 U4732 ( .A(n5044), .B(n5043), .Z(n5045));
+ OR2 U4733 ( .A(n5046), .B(n5047), .Z(n5043));
+ IV2 U4734 ( .A(n5048), .Z(n5047));
+ OR2 U4735 ( .A(n5049), .B(n5050), .Z(n5048));
+ AN2 U4736 ( .A(n5050), .B(n5049), .Z(n5046));
+ AN2 U4737 ( .A(n5051), .B(n5052), .Z(n5049));
+ OR2 U4738 ( .A(n4319), .B(po013), .Z(n5052));
+ OR2 U4739 ( .A(n5053), .B(po004), .Z(n5051));
+ IV2 U4740 ( .A(po013), .Z(n5053));
+ OR2 U4741 ( .A(n5054), .B(n5055), .Z(n5050));
+ AN2 U4742 ( .A(po028), .B(n4013), .Z(n5055));
+ AN2 U4743 ( .A(po040), .B(n5056), .Z(n5054));
+ AN2 U4744 ( .A(n5057), .B(n5058), .Z(n5044));
+ OR2 U4745 ( .A(n5059), .B(n5060), .Z(n5058));
+ IV2 U4746 ( .A(n5061), .Z(n5059));
+ OR2 U4747 ( .A(n5062), .B(n5061), .Z(n5057));
+ OR2 U4748 ( .A(n5063), .B(n5064), .Z(n5061));
+ AN2 U4749 ( .A(po064), .B(n4128), .Z(n5064));
+ AN2 U4750 ( .A(po085), .B(n4133), .Z(n5063));
+ IV2 U4751 ( .A(n5060), .Z(n5062));
+ OR2 U4752 ( .A(n5065), .B(n5066), .Z(n5060));
+ AN2 U4753 ( .A(po091), .B(n3265), .Z(n5066));
+ AN2 U4754 ( .A(po103), .B(n4201), .Z(n5065));
+ IV2 U4755 ( .A(n5067), .Z(po041));
+ AN2 U4756 ( .A(n5068), .B(pi193), .Z(n5067));
+ AN2 U4757 ( .A(pi057), .B(n5069), .Z(n5068));
+ IV2 U4758 ( .A(pi037), .Z(n5069));
+ OR2 U4759 ( .A(n5070), .B(n5071), .Z(po037));
+ AN2 U4760 ( .A(n3021), .B(n5072), .Z(n5071));
+ OR2 U4761 ( .A(n5073), .B(n5074), .Z(n5072));
+ AN2 U4762 ( .A(n3018), .B(n5075), .Z(n5073));
+ OR2 U4763 ( .A(n5076), .B(n5077), .Z(n5075));
+ AN2 U4764 ( .A(n4663), .B(n3284), .Z(n5076));
+ OR2 U4765 ( .A(n5078), .B(n5079), .Z(n4663));
+ AN2 U4766 ( .A(n3064), .B(n3108), .Z(n5079));
+ AN2 U4767 ( .A(n3173), .B(n3115), .Z(n5078));
+ AN2 U4768 ( .A(n3083), .B(n5080), .Z(n5070));
+ OR2 U4769 ( .A(n5081), .B(n5082), .Z(n5080));
+ OR2 U4770 ( .A(n5083), .B(n5084), .Z(n5082));
+ AN2 U4771 ( .A(po070), .B(n4327), .Z(n5084));
+ OR2 U4772 ( .A(n5085), .B(n5086), .Z(n4327));
+ OR2 U4773 ( .A(n5087), .B(n5088), .Z(n5086));
+ AN2 U4774 ( .A(n3273), .B(n5089), .Z(n5088));
+ IV2 U4775 ( .A(n3284), .Z(n3273));
+ AN2 U4776 ( .A(n5090), .B(n3274), .Z(n5087));
+ OR2 U4777 ( .A(n5091), .B(n3282), .Z(n5085));
+ IV2 U4778 ( .A(n4666), .Z(n3282));
+ AN2 U4779 ( .A(n5092), .B(n3199), .Z(n5083));
+ OR2 U4780 ( .A(n5093), .B(n5094), .Z(n5092));
+ OR2 U4781 ( .A(n5095), .B(n5096), .Z(n5094));
+ AN2 U4782 ( .A(n5090), .B(po010), .Z(n5096));
+ AN2 U4783 ( .A(n3037), .B(n3061), .Z(n5090));
+ AN2 U4784 ( .A(n5097), .B(n5098), .Z(n5095));
+ AN2 U4785 ( .A(n3037), .B(n5099), .Z(n5098));
+ AN2 U4786 ( .A(n5100), .B(n3120), .Z(n5097));
+ OR2 U4787 ( .A(n5101), .B(n3061), .Z(n3120));
+ AN2 U4788 ( .A(n3106), .B(pi192), .Z(n3061));
+ AN2 U4789 ( .A(po010), .B(pi192), .Z(n5101));
+ AN2 U4790 ( .A(n3082), .B(pi192), .Z(n5093));
+ IV2 U4791 ( .A(n3108), .Z(n3082));
+ OR2 U4792 ( .A(pi033), .B(n3286), .Z(n3108));
+ OR2 U4793 ( .A(n5102), .B(n5103), .Z(n5081));
+ AN2 U4794 ( .A(n3015), .B(n5104), .Z(n5103));
+ IV2 U4795 ( .A(n3018), .Z(n3015));
+ AN2 U4796 ( .A(n5105), .B(n3205), .Z(n5102));
+ OR2 U4797 ( .A(n5106), .B(n5107), .Z(n5105));
+ OR2 U4798 ( .A(n5091), .B(n5108), .Z(n5107));
+ AN2 U4799 ( .A(n5100), .B(n5109), .Z(n5108));
+ OR2 U4800 ( .A(n5110), .B(n5111), .Z(n5109));
+ AN2 U4801 ( .A(n5112), .B(n2925), .Z(n5111));
+ AN2 U4802 ( .A(po010), .B(n5089), .Z(n5112));
+ IV2 U4803 ( .A(n3100), .Z(n5089));
+ AN2 U4804 ( .A(n5113), .B(n3080), .Z(n5110));
+ AN2 U4805 ( .A(n2837), .B(po010), .Z(n3080));
+ AN2 U4806 ( .A(n3112), .B(n5099), .Z(n5113));
+ AN2 U4807 ( .A(n3065), .B(n5114), .Z(n5091));
+ AN2 U4808 ( .A(n3112), .B(n3274), .Z(n5114));
+ IV2 U4809 ( .A(n3280), .Z(n3274));
+ AN2 U4810 ( .A(n2837), .B(n5115), .Z(n3065));
+ AN2 U4811 ( .A(n3073), .B(n2837), .Z(n5106));
+ IV2 U4812 ( .A(n3115), .Z(n3073));
+ OR2 U4813 ( .A(pi141), .B(n3286), .Z(n3115));
+ OR2 U4814 ( .A(n5116), .B(n5117), .Z(po034));
+ OR2 U4815 ( .A(n5118), .B(n5119), .Z(n5117));
+ AN2 U4816 ( .A(pi054), .B(n5120), .Z(n5119));
+ AN2 U4817 ( .A(n5121), .B(n5122), .Z(n5118));
+ AN2 U4818 ( .A(n5123), .B(n5124), .Z(n5122));
+ OR2 U4819 ( .A(po085), .B(po064), .Z(n5124));
+ OR2 U4820 ( .A(n4125), .B(n4133), .Z(n5123));
+ AN2 U4821 ( .A(n4129), .B(n4128), .Z(n4125));
+ AN2 U4822 ( .A(pi052), .B(n5125), .Z(n5121));
+ AN2 U4823 ( .A(n5126), .B(n5127), .Z(n5116));
+ OR2 U4824 ( .A(n4167), .B(n5128), .Z(n5127));
+ OR2 U4825 ( .A(n5129), .B(n5130), .Z(n5128));
+ AN2 U4826 ( .A(n5131), .B(po064), .Z(n5130));
+ AN2 U4827 ( .A(pi054), .B(po085), .Z(n5131));
+ AN2 U4828 ( .A(n4129), .B(n4133), .Z(n5129));
+ OR2 U4829 ( .A(n5132), .B(n5133), .Z(po033));
+ AN2 U4830 ( .A(n3371), .B(n5134), .Z(n5133));
+ OR2 U4831 ( .A(n5135), .B(n5136), .Z(n5134));
+ AN2 U4832 ( .A(n5137), .B(n3412), .Z(n5132));
+ OR2 U4833 ( .A(n5138), .B(n5139), .Z(n5137));
+ OR2 U4834 ( .A(n5140), .B(n5141), .Z(po030));
+ AN2 U4835 ( .A(n5142), .B(pi192), .Z(n5141));
+ OR2 U4836 ( .A(n5143), .B(n5144), .Z(n5142));
+ AN2 U4837 ( .A(n2834), .B(n5145), .Z(n5144));
+ OR2 U4838 ( .A(n5146), .B(n5147), .Z(n5145));
+ AN2 U4839 ( .A(n2998), .B(n3847), .Z(n5147));
+ AN2 U4840 ( .A(n5148), .B(n5149), .Z(n5146));
+ OR2 U4841 ( .A(n2862), .B(n5150), .Z(n5149));
+ OR2 U4842 ( .A(n2880), .B(n5151), .Z(n5150));
+ AN2 U4843 ( .A(n2887), .B(n2901), .Z(n5151));
+ AN2 U4844 ( .A(n2891), .B(n5152), .Z(n5148));
+ IV2 U4845 ( .A(n5153), .Z(n5152));
+ AN2 U4846 ( .A(n5154), .B(n2833), .Z(n5143));
+ OR2 U4847 ( .A(n5155), .B(n5156), .Z(n5154));
+ AN2 U4848 ( .A(n5157), .B(n5158), .Z(n5155));
+ AN2 U4849 ( .A(n2930), .B(n2878), .Z(n5158));
+ AN2 U4850 ( .A(n5159), .B(n2837), .Z(n5140));
+ OR2 U4851 ( .A(n5160), .B(n5161), .Z(n5159));
+ AN2 U4852 ( .A(n2846), .B(n5162), .Z(n5161));
+ OR2 U4853 ( .A(n5163), .B(n5164), .Z(n5162));
+ AN2 U4854 ( .A(n2998), .B(n5165), .Z(n5164));
+ AN2 U4855 ( .A(n5166), .B(n5167), .Z(n5163));
+ OR2 U4856 ( .A(n5168), .B(n5169), .Z(n5167));
+ AN2 U4857 ( .A(n3222), .B(n2946), .Z(n5168));
+ OR2 U4858 ( .A(n5170), .B(n2959), .Z(n3222));
+ AN2 U4859 ( .A(n2982), .B(n2901), .Z(n2959));
+ AN2 U4860 ( .A(po107), .B(n5171), .Z(n5170));
+ IV2 U4861 ( .A(n2981), .Z(n5171));
+ AN2 U4862 ( .A(pi081), .B(pi200), .Z(n2981));
+ AN2 U4863 ( .A(n2947), .B(n5172), .Z(n5166));
+ AN2 U4864 ( .A(n5173), .B(n2845), .Z(n5160));
+ OR2 U4865 ( .A(n5174), .B(n5175), .Z(n5173));
+ AN2 U4866 ( .A(n5157), .B(n5176), .Z(n5174));
+ AN2 U4867 ( .A(n2908), .B(n2938), .Z(n5176));
+ OR2 U4868 ( .A(pi081), .B(n2931), .Z(n2938));
+ IV2 U4869 ( .A(n5169), .Z(n2908));
+ AN2 U4870 ( .A(n2861), .B(pi200), .Z(n5157));
+ OR2 U4871 ( .A(n5177), .B(n5178), .Z(po029));
+ OR2 U4872 ( .A(n5179), .B(n5180), .Z(n5178));
+ AN2 U4873 ( .A(n5181), .B(n4313), .Z(n5180));
+ AN2 U4874 ( .A(n3945), .B(n5182), .Z(n5179));
+ OR2 U4875 ( .A(n5183), .B(n5184), .Z(n5182));
+ OR2 U4876 ( .A(n5185), .B(n5186), .Z(n5184));
+ AN2 U4877 ( .A(n5187), .B(pi186), .Z(n5186));
+ OR2 U4878 ( .A(n5188), .B(n5189), .Z(n5187));
+ AN2 U4879 ( .A(n5190), .B(n5191), .Z(n5189));
+ AN2 U4880 ( .A(n5192), .B(pi124), .Z(n5188));
+ IV2 U4881 ( .A(n5190), .Z(n5192));
+ AN2 U4882 ( .A(n5193), .B(n5194), .Z(n5185));
+ OR2 U4883 ( .A(n5195), .B(n5196), .Z(n5193));
+ AN2 U4884 ( .A(n5190), .B(pi124), .Z(n5196));
+ OR2 U4885 ( .A(n5197), .B(n5198), .Z(n5190));
+ AN2 U4886 ( .A(n5199), .B(n5200), .Z(n5198));
+ AN2 U4887 ( .A(n5201), .B(pi109), .Z(n5197));
+ IV2 U4888 ( .A(n5199), .Z(n5201));
+ AN2 U4889 ( .A(n5202), .B(n5191), .Z(n5195));
+ OR2 U4890 ( .A(n5203), .B(n5204), .Z(n5202));
+ AN2 U4891 ( .A(n5199), .B(pi109), .Z(n5204));
+ OR2 U4892 ( .A(n5205), .B(n5206), .Z(n5199));
+ AN2 U4893 ( .A(n5207), .B(n5208), .Z(n5206));
+ AN2 U4894 ( .A(n5181), .B(pi055), .Z(n5205));
+ AN2 U4895 ( .A(n5209), .B(n5200), .Z(n5203));
+ AN2 U4896 ( .A(pi055), .B(n5207), .Z(n5209));
+ AN2 U4897 ( .A(n5210), .B(n5211), .Z(n5183));
+ OR2 U4898 ( .A(n5212), .B(n5213), .Z(n5211));
+ IV2 U4899 ( .A(n5214), .Z(n5210));
+ AN2 U4900 ( .A(n5213), .B(n5212), .Z(n5214));
+ OR2 U4901 ( .A(n5215), .B(n5216), .Z(n5212));
+ IV2 U4902 ( .A(n5217), .Z(n5216));
+ OR2 U4903 ( .A(n5218), .B(pi006), .Z(n5217));
+ AN2 U4904 ( .A(n5218), .B(pi006), .Z(n5215));
+ AN2 U4905 ( .A(n5219), .B(n5220), .Z(n5218));
+ OR2 U4906 ( .A(n5221), .B(pi061), .Z(n5220));
+ IV2 U4907 ( .A(pi051), .Z(n5221));
+ OR2 U4908 ( .A(n5222), .B(pi051), .Z(n5219));
+ IV2 U4909 ( .A(pi061), .Z(n5222));
+ AN2 U4910 ( .A(n5223), .B(n5224), .Z(n5213));
+ IV2 U4911 ( .A(n5225), .Z(n5224));
+ AN2 U4912 ( .A(n5226), .B(n5227), .Z(n5225));
+ OR2 U4913 ( .A(n5227), .B(n5226), .Z(n5223));
+ OR2 U4914 ( .A(n5228), .B(n5229), .Z(n5226));
+ AN2 U4915 ( .A(pi093), .B(n5230), .Z(n5229));
+ IV2 U4916 ( .A(n5231), .Z(n5228));
+ OR2 U4917 ( .A(n5230), .B(pi093), .Z(n5231));
+ IV2 U4918 ( .A(pi122), .Z(n5230));
+ AN2 U4919 ( .A(n5232), .B(n5233), .Z(n5227));
+ IV2 U4920 ( .A(n5234), .Z(n5233));
+ AN2 U4921 ( .A(pi134), .B(n5235), .Z(n5234));
+ OR2 U4922 ( .A(n5235), .B(pi134), .Z(n5232));
+ IV2 U4923 ( .A(pi198), .Z(n5235));
+ OR2 U4924 ( .A(n5236), .B(n5237), .Z(n5177));
+ AN2 U4925 ( .A(n5238), .B(n2837), .Z(n5237));
+ OR2 U4926 ( .A(n5239), .B(n5240), .Z(n5238));
+ AN2 U4927 ( .A(n5241), .B(n5242), .Z(n5240));
+ OR2 U4928 ( .A(n3809), .B(n5243), .Z(n5242));
+ IV2 U4929 ( .A(n3812), .Z(n3809));
+ OR2 U4930 ( .A(n5244), .B(n3812), .Z(n5241));
+ AN2 U4931 ( .A(n5245), .B(n5246), .Z(n3812));
+ IV2 U4932 ( .A(n5247), .Z(n5246));
+ AN2 U4933 ( .A(n5248), .B(n5249), .Z(n5247));
+ OR2 U4934 ( .A(n5249), .B(n5248), .Z(n5245));
+ OR2 U4935 ( .A(n5250), .B(n5251), .Z(n5248));
+ AN2 U4936 ( .A(pi040), .B(n5252), .Z(n5251));
+ IV2 U4937 ( .A(pi095), .Z(n5252));
+ AN2 U4938 ( .A(pi095), .B(n4735), .Z(n5250));
+ AN2 U4939 ( .A(n5253), .B(n5254), .Z(n5249));
+ OR2 U4940 ( .A(n4747), .B(pi156), .Z(n5254));
+ IV2 U4941 ( .A(pi151), .Z(n4747));
+ OR2 U4942 ( .A(n4648), .B(pi151), .Z(n5253));
+ AN2 U4943 ( .A(n5255), .B(n5256), .Z(n5239));
+ OR2 U4944 ( .A(n3815), .B(n5257), .Z(n5256));
+ OR2 U4945 ( .A(n5258), .B(n3818), .Z(n5255));
+ IV2 U4946 ( .A(n3815), .Z(n3818));
+ OR2 U4947 ( .A(n5259), .B(n5260), .Z(n3815));
+ AN2 U4948 ( .A(n5261), .B(n5262), .Z(n5260));
+ IV2 U4949 ( .A(n5263), .Z(n5259));
+ OR2 U4950 ( .A(n5262), .B(n5261), .Z(n5263));
+ OR2 U4951 ( .A(n5264), .B(n5265), .Z(n5261));
+ AN2 U4952 ( .A(pi128), .B(n3177), .Z(n5265));
+ AN2 U4953 ( .A(pi141), .B(n3205), .Z(n5264));
+ AN2 U4954 ( .A(n5266), .B(n5267), .Z(n5262));
+ OR2 U4955 ( .A(n5115), .B(pi185), .Z(n5267));
+ OR2 U4956 ( .A(n5268), .B(pi174), .Z(n5266));
+ IV2 U4957 ( .A(pi185), .Z(n5268));
+ AN2 U4958 ( .A(pi192), .B(n5269), .Z(n5236));
+ OR2 U4959 ( .A(n5270), .B(n5271), .Z(n5269));
+ OR2 U4960 ( .A(n5272), .B(n5273), .Z(n5271));
+ AN2 U4961 ( .A(n5274), .B(n5275), .Z(n5273));
+ IV2 U4962 ( .A(n5276), .Z(n5275));
+ AN2 U4963 ( .A(n5277), .B(n5278), .Z(n5276));
+ OR2 U4964 ( .A(n5278), .B(n5277), .Z(n5274));
+ AN2 U4965 ( .A(n5279), .B(n5280), .Z(n5277));
+ OR2 U4966 ( .A(n5243), .B(pi036), .Z(n5280));
+ IV2 U4967 ( .A(n5244), .Z(n5243));
+ OR2 U4968 ( .A(n5244), .B(n5281), .Z(n5279));
+ IV2 U4969 ( .A(pi036), .Z(n5281));
+ OR2 U4970 ( .A(n3871), .B(n5282), .Z(n5244));
+ AN2 U4971 ( .A(n5283), .B(pi192), .Z(n5282));
+ OR2 U4972 ( .A(n5284), .B(n5285), .Z(n5283));
+ AN2 U4973 ( .A(n5286), .B(n5287), .Z(n5285));
+ IV2 U4974 ( .A(n5288), .Z(n5284));
+ OR2 U4975 ( .A(n5287), .B(n5286), .Z(n5288));
+ OR2 U4976 ( .A(n5289), .B(n5290), .Z(n5286));
+ IV2 U4977 ( .A(n5291), .Z(n5290));
+ OR2 U4978 ( .A(n5292), .B(pi017), .Z(n5291));
+ AN2 U4979 ( .A(pi017), .B(n5292), .Z(n5289));
+ AN2 U4980 ( .A(n5293), .B(n5294), .Z(n5292));
+ OR2 U4981 ( .A(n5295), .B(pi083), .Z(n5294));
+ IV2 U4982 ( .A(pi027), .Z(n5295));
+ OR2 U4983 ( .A(n5296), .B(pi027), .Z(n5293));
+ IV2 U4984 ( .A(pi083), .Z(n5296));
+ AN2 U4985 ( .A(n5297), .B(n5298), .Z(n5287));
+ OR2 U4986 ( .A(n5299), .B(pi089), .Z(n5298));
+ IV2 U4987 ( .A(n5300), .Z(n5297));
+ AN2 U4988 ( .A(n5299), .B(pi089), .Z(n5300));
+ AN2 U4989 ( .A(n5301), .B(n5302), .Z(n5299));
+ OR2 U4990 ( .A(n5303), .B(pi162), .Z(n5302));
+ OR2 U4991 ( .A(n5304), .B(pi140), .Z(n5301));
+ IV2 U4992 ( .A(pi162), .Z(n5304));
+ AN2 U4993 ( .A(n5305), .B(n2837), .Z(n3871));
+ OR2 U4994 ( .A(n5306), .B(n5307), .Z(n5305));
+ AN2 U4995 ( .A(n5308), .B(n5309), .Z(n5307));
+ IV2 U4996 ( .A(n5310), .Z(n5306));
+ OR2 U4997 ( .A(n5309), .B(n5308), .Z(n5310));
+ OR2 U4998 ( .A(n5311), .B(n5312), .Z(n5308));
+ IV2 U4999 ( .A(n5313), .Z(n5312));
+ OR2 U5000 ( .A(n5314), .B(pi064), .Z(n5313));
+ AN2 U5001 ( .A(pi064), .B(n5314), .Z(n5311));
+ AN2 U5002 ( .A(n5315), .B(n5316), .Z(n5314));
+ OR2 U5003 ( .A(n4077), .B(pi108), .Z(n5316));
+ OR2 U5004 ( .A(n5317), .B(pi076), .Z(n5315));
+ IV2 U5005 ( .A(pi108), .Z(n5317));
+ AN2 U5006 ( .A(n5318), .B(n5319), .Z(n5309));
+ OR2 U5007 ( .A(n5320), .B(pi114), .Z(n5319));
+ IV2 U5008 ( .A(n5321), .Z(n5320));
+ OR2 U5009 ( .A(n5321), .B(n5322), .Z(n5318));
+ OR2 U5010 ( .A(n5323), .B(n5324), .Z(n5321));
+ AN2 U5011 ( .A(pi160), .B(n4074), .Z(n5324));
+ AN2 U5012 ( .A(pi170), .B(n4358), .Z(n5323));
+ OR2 U5013 ( .A(n5325), .B(n5326), .Z(n5278));
+ IV2 U5014 ( .A(n5327), .Z(n5326));
+ OR2 U5015 ( .A(n5328), .B(pi101), .Z(n5327));
+ AN2 U5016 ( .A(n5328), .B(pi101), .Z(n5325));
+ AN2 U5017 ( .A(n5329), .B(n5330), .Z(n5328));
+ OR2 U5018 ( .A(n5331), .B(pi205), .Z(n5330));
+ OR2 U5019 ( .A(n5332), .B(pi168), .Z(n5329));
+ IV2 U5020 ( .A(pi205), .Z(n5332));
+ AN2 U5021 ( .A(n5333), .B(n5334), .Z(n5272));
+ AN2 U5022 ( .A(n5335), .B(n5200), .Z(n5334));
+ IV2 U5023 ( .A(pi109), .Z(n5200));
+ AN2 U5024 ( .A(n5191), .B(n5194), .Z(n5335));
+ IV2 U5025 ( .A(pi186), .Z(n5194));
+ IV2 U5026 ( .A(pi124), .Z(n5191));
+ AN2 U5027 ( .A(n5181), .B(n5208), .Z(n5333));
+ IV2 U5028 ( .A(pi055), .Z(n5208));
+ IV2 U5029 ( .A(n5207), .Z(n5181));
+ OR2 U5030 ( .A(n3977), .B(n5336), .Z(n5207));
+ AN2 U5031 ( .A(n5337), .B(pi192), .Z(n5336));
+ OR2 U5032 ( .A(n5338), .B(n5339), .Z(n5337));
+ AN2 U5033 ( .A(n5340), .B(n5341), .Z(n5339));
+ IV2 U5034 ( .A(n5342), .Z(n5338));
+ OR2 U5035 ( .A(n5341), .B(n5340), .Z(n5342));
+ OR2 U5036 ( .A(n5343), .B(n5344), .Z(n5340));
+ IV2 U5037 ( .A(n5345), .Z(n5344));
+ OR2 U5038 ( .A(n5346), .B(n5347), .Z(n5345));
+ AN2 U5039 ( .A(n5346), .B(n5347), .Z(n5343));
+ AN2 U5040 ( .A(n5348), .B(n5349), .Z(n5346));
+ OR2 U5041 ( .A(n5350), .B(pi099), .Z(n5349));
+ OR2 U5042 ( .A(n5351), .B(pi018), .Z(n5348));
+ IV2 U5043 ( .A(pi099), .Z(n5351));
+ AN2 U5044 ( .A(n5352), .B(n5353), .Z(n5341));
+ OR2 U5045 ( .A(n5354), .B(pi150), .Z(n5353));
+ IV2 U5046 ( .A(n5355), .Z(n5352));
+ AN2 U5047 ( .A(pi150), .B(n5354), .Z(n5355));
+ AN2 U5048 ( .A(n5356), .B(n5357), .Z(n5354));
+ OR2 U5049 ( .A(n5358), .B(pi180), .Z(n5357));
+ OR2 U5050 ( .A(n5359), .B(pi172), .Z(n5356));
+ IV2 U5051 ( .A(pi180), .Z(n5359));
+ AN2 U5052 ( .A(n5360), .B(n2837), .Z(n3977));
+ AN2 U5053 ( .A(n5361), .B(n5362), .Z(n5360));
+ IV2 U5054 ( .A(n5363), .Z(n5362));
+ AN2 U5055 ( .A(n5364), .B(n5365), .Z(n5363));
+ OR2 U5056 ( .A(n5365), .B(n5364), .Z(n5361));
+ OR2 U5057 ( .A(n5366), .B(n5367), .Z(n5364));
+ AN2 U5058 ( .A(n5368), .B(n3261), .Z(n5367));
+ AN2 U5059 ( .A(n5369), .B(n3321), .Z(n5366));
+ IV2 U5060 ( .A(n5368), .Z(n5369));
+ OR2 U5061 ( .A(n5370), .B(n5371), .Z(n5368));
+ AN2 U5062 ( .A(pi003), .B(n5372), .Z(n5371));
+ AN2 U5063 ( .A(pi130), .B(n3597), .Z(n5370));
+ AN2 U5064 ( .A(n5373), .B(n5374), .Z(n5365));
+ OR2 U5065 ( .A(n5375), .B(pi142), .Z(n5374));
+ IV2 U5066 ( .A(n5376), .Z(n5375));
+ OR2 U5067 ( .A(n5376), .B(n4440), .Z(n5373));
+ OR2 U5068 ( .A(n5377), .B(n5378), .Z(n5376));
+ AN2 U5069 ( .A(pi177), .B(n5379), .Z(n5378));
+ AN2 U5070 ( .A(pi195), .B(n5380), .Z(n5377));
+ IV2 U5071 ( .A(pi177), .Z(n5380));
+ AN2 U5072 ( .A(n5381), .B(n5382), .Z(n5270));
+ IV2 U5073 ( .A(n5383), .Z(n5382));
+ AN2 U5074 ( .A(n5384), .B(n5385), .Z(n5383));
+ OR2 U5075 ( .A(n5385), .B(n5384), .Z(n5381));
+ AN2 U5076 ( .A(n5386), .B(n5387), .Z(n5384));
+ OR2 U5077 ( .A(n5257), .B(pi001), .Z(n5387));
+ IV2 U5078 ( .A(n5258), .Z(n5257));
+ OR2 U5079 ( .A(n5258), .B(n5388), .Z(n5386));
+ IV2 U5080 ( .A(pi001), .Z(n5388));
+ OR2 U5081 ( .A(n3831), .B(n5389), .Z(n5258));
+ AN2 U5082 ( .A(n5390), .B(pi192), .Z(n5389));
+ OR2 U5083 ( .A(n5391), .B(n5392), .Z(n5390));
+ AN2 U5084 ( .A(n5393), .B(n5394), .Z(n5392));
+ IV2 U5085 ( .A(n5395), .Z(n5391));
+ OR2 U5086 ( .A(n5394), .B(n5393), .Z(n5395));
+ OR2 U5087 ( .A(n5396), .B(n5397), .Z(n5393));
+ IV2 U5088 ( .A(n5398), .Z(n5397));
+ OR2 U5089 ( .A(n5399), .B(pi038), .Z(n5398));
+ AN2 U5090 ( .A(pi038), .B(n5399), .Z(n5396));
+ AN2 U5091 ( .A(n5400), .B(n5401), .Z(n5399));
+ OR2 U5092 ( .A(n5402), .B(pi103), .Z(n5401));
+ IV2 U5093 ( .A(pi053), .Z(n5402));
+ OR2 U5094 ( .A(n5403), .B(pi053), .Z(n5400));
+ IV2 U5095 ( .A(pi103), .Z(n5403));
+ AN2 U5096 ( .A(n5404), .B(n5405), .Z(n5394));
+ OR2 U5097 ( .A(n5406), .B(pi121), .Z(n5405));
+ IV2 U5098 ( .A(n5407), .Z(n5404));
+ AN2 U5099 ( .A(n5406), .B(pi121), .Z(n5407));
+ AN2 U5100 ( .A(n5408), .B(n5409), .Z(n5406));
+ OR2 U5101 ( .A(n5410), .B(pi184), .Z(n5409));
+ IV2 U5102 ( .A(pi149), .Z(n5410));
+ OR2 U5103 ( .A(n5411), .B(pi149), .Z(n5408));
+ IV2 U5104 ( .A(pi184), .Z(n5411));
+ AN2 U5105 ( .A(n5412), .B(n2837), .Z(n3831));
+ OR2 U5106 ( .A(n5413), .B(n5414), .Z(n5412));
+ IV2 U5107 ( .A(n5415), .Z(n5414));
+ OR2 U5108 ( .A(n5416), .B(n5417), .Z(n5415));
+ AN2 U5109 ( .A(n5417), .B(n5416), .Z(n5413));
+ AN2 U5110 ( .A(n5418), .B(n5419), .Z(n5416));
+ OR2 U5111 ( .A(n5420), .B(pi081), .Z(n5419));
+ IV2 U5112 ( .A(n5421), .Z(n5420));
+ OR2 U5113 ( .A(n5421), .B(n2982), .Z(n5418));
+ OR2 U5114 ( .A(n5422), .B(n5423), .Z(n5421));
+ AN2 U5115 ( .A(pi082), .B(n5424), .Z(n5423));
+ IV2 U5116 ( .A(pi092), .Z(n5424));
+ AN2 U5117 ( .A(pi092), .B(n2957), .Z(n5422));
+ OR2 U5118 ( .A(n5425), .B(n5426), .Z(n5417));
+ AN2 U5119 ( .A(n5427), .B(n5165), .Z(n5426));
+ AN2 U5120 ( .A(n5428), .B(pi107), .Z(n5425));
+ IV2 U5121 ( .A(n5427), .Z(n5428));
+ OR2 U5122 ( .A(n5429), .B(n5430), .Z(n5427));
+ AN2 U5123 ( .A(pi201), .B(n5431), .Z(n5430));
+ AN2 U5124 ( .A(pi206), .B(n3141), .Z(n5429));
+ OR2 U5125 ( .A(n5432), .B(n5433), .Z(n5385));
+ IV2 U5126 ( .A(n5434), .Z(n5433));
+ OR2 U5127 ( .A(n5435), .B(pi059), .Z(n5434));
+ AN2 U5128 ( .A(n5435), .B(pi059), .Z(n5432));
+ AN2 U5129 ( .A(n5436), .B(n5437), .Z(n5435));
+ OR2 U5130 ( .A(n5438), .B(pi197), .Z(n5437));
+ IV2 U5131 ( .A(pi131), .Z(n5438));
+ OR2 U5132 ( .A(n5439), .B(pi131), .Z(n5436));
+ OR2 U5133 ( .A(n5440), .B(n5441), .Z(po026));
+ AN2 U5134 ( .A(n3355), .B(n5442), .Z(n5441));
+ OR2 U5135 ( .A(n5443), .B(n5444), .Z(n5442));
+ OR2 U5136 ( .A(n5445), .B(n5446), .Z(n5444));
+ AN2 U5137 ( .A(po036), .B(n5447), .Z(n5446));
+ OR2 U5138 ( .A(n4418), .B(n5448), .Z(n5447));
+ AN2 U5139 ( .A(n5449), .B(n3236), .Z(n5445));
+ AN2 U5140 ( .A(n5450), .B(n5451), .Z(n5449));
+ OR2 U5141 ( .A(n5452), .B(n2837), .Z(n5451));
+ OR2 U5142 ( .A(pi192), .B(n5453), .Z(n5450));
+ AN2 U5143 ( .A(n4418), .B(n5448), .Z(n5443));
+ AN2 U5144 ( .A(n3352), .B(n5454), .Z(n5440));
+ IV2 U5145 ( .A(n5455), .Z(po022));
+ AN2 U5146 ( .A(n5456), .B(n5457), .Z(n5455));
+ AN2 U5147 ( .A(pi074), .B(pi046), .Z(n5457));
+ AN2 U5148 ( .A(pi178), .B(pi113), .Z(n5456));
+ OR2 U5149 ( .A(n5458), .B(n5459), .Z(po019));
+ AN2 U5150 ( .A(n4478), .B(n5460), .Z(n5459));
+ OR2 U5151 ( .A(n5461), .B(n4511), .Z(n5460));
+ OR2 U5152 ( .A(n5462), .B(n5463), .Z(n4511));
+ OR2 U5153 ( .A(n5464), .B(n5465), .Z(n5463));
+ AN2 U5154 ( .A(n5466), .B(pi192), .Z(n5465));
+ AN2 U5155 ( .A(n5467), .B(n2837), .Z(n5464));
+ AN2 U5156 ( .A(n4475), .B(n5468), .Z(n5458));
+ OR2 U5157 ( .A(n5469), .B(n5470), .Z(n5468));
+ OR2 U5158 ( .A(n5471), .B(n4509), .Z(n5470));
+ OR2 U5159 ( .A(n5472), .B(n5473), .Z(n4509));
+ OR2 U5160 ( .A(n5474), .B(n5475), .Z(n5473));
+ AN2 U5161 ( .A(n5476), .B(n4078), .Z(n5475));
+ AN2 U5162 ( .A(n5477), .B(n5322), .Z(n5476));
+ AN2 U5163 ( .A(n5478), .B(n4551), .Z(n5472));
+ IV2 U5164 ( .A(n4544), .Z(n4551));
+ OR2 U5165 ( .A(n4561), .B(n4066), .Z(n4544));
+ AN2 U5166 ( .A(pi192), .B(n3901), .Z(n5478));
+ AN2 U5167 ( .A(po102), .B(n4347), .Z(n5471));
+ OR2 U5168 ( .A(n5479), .B(n4524), .Z(n4347));
+ AN2 U5169 ( .A(n5480), .B(n4078), .Z(n4524));
+ IV2 U5170 ( .A(n4066), .Z(n4078));
+ AN2 U5171 ( .A(n4521), .B(n4072), .Z(n5479));
+ OR2 U5172 ( .A(n5481), .B(n5482), .Z(n4521));
+ AN2 U5173 ( .A(po059), .B(n5480), .Z(n5482));
+ OR2 U5174 ( .A(n5483), .B(po024), .Z(n5480));
+ AN2 U5175 ( .A(n5477), .B(n4074), .Z(n5481));
+ OR2 U5176 ( .A(n5484), .B(n5485), .Z(n5469));
+ AN2 U5177 ( .A(n4517), .B(n3780), .Z(n5485));
+ OR2 U5178 ( .A(n5486), .B(n5487), .Z(n4517));
+ AN2 U5179 ( .A(n4356), .B(n5488), .Z(n5487));
+ AN2 U5180 ( .A(n4076), .B(n5489), .Z(n4356));
+ AN2 U5181 ( .A(n4077), .B(n4578), .Z(n5489));
+ AN2 U5182 ( .A(n5490), .B(n4543), .Z(n5486));
+ AN2 U5183 ( .A(n4348), .B(n4353), .Z(n4543));
+ AN2 U5184 ( .A(n3890), .B(n5491), .Z(n5490));
+ AN2 U5185 ( .A(n4512), .B(n4072), .Z(n5484));
+ OR2 U5186 ( .A(n5492), .B(n3773), .Z(n4072));
+ AN2 U5187 ( .A(po025), .B(n3780), .Z(n5492));
+ IV2 U5188 ( .A(n4087), .Z(n3780));
+ OR2 U5189 ( .A(n5493), .B(n5494), .Z(n4512));
+ OR2 U5190 ( .A(n5495), .B(n5496), .Z(n5494));
+ AN2 U5191 ( .A(n5497), .B(pi192), .Z(n5496));
+ AN2 U5192 ( .A(n5498), .B(n4348), .Z(n5497));
+ OR2 U5193 ( .A(n5499), .B(n5500), .Z(n5498));
+ AN2 U5194 ( .A(po102), .B(n3880), .Z(n5500));
+ AN2 U5195 ( .A(n4353), .B(n3901), .Z(n5499));
+ AN2 U5196 ( .A(n5501), .B(n4076), .Z(n5495));
+ AN2 U5197 ( .A(n5488), .B(n4358), .Z(n5501));
+ AN2 U5198 ( .A(n5502), .B(n4076), .Z(n5493));
+ AN2 U5199 ( .A(n2837), .B(n5503), .Z(n4076));
+ AN2 U5200 ( .A(po024), .B(n5322), .Z(n5502));
+ OR2 U5201 ( .A(n5504), .B(n5505), .Z(po074));
+ AN2 U5202 ( .A(n5506), .B(n5507), .Z(n5505));
+ OR2 U5203 ( .A(n4167), .B(n5508), .Z(n5507));
+ OR2 U5204 ( .A(pi054), .B(n5509), .Z(n5508));
+ AN2 U5205 ( .A(pi025), .B(pi146), .Z(n5509));
+ OR2 U5206 ( .A(n5510), .B(n5511), .Z(n5506));
+ OR2 U5207 ( .A(n5512), .B(n5513), .Z(n5511));
+ AN2 U5208 ( .A(n3926), .B(n5514), .Z(n5513));
+ OR2 U5209 ( .A(n5515), .B(n5516), .Z(n5514));
+ OR2 U5210 ( .A(n5517), .B(n5518), .Z(n5516));
+ OR2 U5211 ( .A(pi056), .B(pi035), .Z(n5518));
+ OR2 U5212 ( .A(pi100), .B(n5519), .Z(n5515));
+ OR2 U5213 ( .A(pi190), .B(pi126), .Z(n5519));
+ AN2 U5214 ( .A(n5520), .B(n4319), .Z(n5512));
+ OR2 U5215 ( .A(n5521), .B(n5522), .Z(n5520));
+ AN2 U5216 ( .A(pi198), .B(n3945), .Z(n5522));
+ AN2 U5217 ( .A(n5523), .B(n5524), .Z(n5521));
+ AN2 U5218 ( .A(n5525), .B(n5517), .Z(n5524));
+ AN2 U5219 ( .A(n5056), .B(n4201), .Z(n5525));
+ AN2 U5220 ( .A(n4391), .B(pi192), .Z(n5523));
+ OR2 U5221 ( .A(n5526), .B(n5527), .Z(n5510));
+ AN2 U5222 ( .A(n5528), .B(n5529), .Z(n5527));
+ OR2 U5223 ( .A(pi198), .B(n4319), .Z(n5529));
+ OR2 U5224 ( .A(n5530), .B(n5531), .Z(n5528));
+ AN2 U5225 ( .A(n3945), .B(n5532), .Z(n5531));
+ OR2 U5226 ( .A(n5533), .B(n5534), .Z(n5532));
+ AN2 U5227 ( .A(pi061), .B(n4013), .Z(n5534));
+ AN2 U5228 ( .A(n5535), .B(pi134), .Z(n5533));
+ AN2 U5229 ( .A(n5536), .B(n4201), .Z(n5535));
+ AN2 U5230 ( .A(n5537), .B(n5538), .Z(n5530));
+ AN2 U5231 ( .A(n5536), .B(n3261), .Z(n5538));
+ OR2 U5232 ( .A(pi061), .B(n4013), .Z(n5536));
+ AN2 U5233 ( .A(n5539), .B(n5540), .Z(n5537));
+ OR2 U5234 ( .A(pi134), .B(n4201), .Z(n5540));
+ OR2 U5235 ( .A(n5541), .B(n5542), .Z(n5539));
+ AN2 U5236 ( .A(n5543), .B(n5517), .Z(n5542));
+ AN2 U5237 ( .A(pi192), .B(n5544), .Z(n5541));
+ OR2 U5238 ( .A(n5545), .B(n5546), .Z(n5544));
+ AN2 U5239 ( .A(pi006), .B(n3265), .Z(n5546));
+ AN2 U5240 ( .A(n5543), .B(n5056), .Z(n5545));
+ OR2 U5241 ( .A(pi006), .B(n3265), .Z(n5543));
+ AN2 U5242 ( .A(n5547), .B(n5548), .Z(n5526));
+ AN2 U5243 ( .A(n5549), .B(n5550), .Z(n5548));
+ AN2 U5244 ( .A(n5517), .B(n2837), .Z(n5550));
+ OR2 U5245 ( .A(n5551), .B(n5552), .Z(n5517));
+ OR2 U5246 ( .A(n5553), .B(n5554), .Z(n5552));
+ AN2 U5247 ( .A(n3945), .B(n5555), .Z(n5554));
+ OR2 U5248 ( .A(n5556), .B(n5557), .Z(n5555));
+ OR2 U5249 ( .A(n5558), .B(n5559), .Z(n5557));
+ AN2 U5250 ( .A(n5560), .B(n3380), .Z(n5559));
+ AN2 U5251 ( .A(n5561), .B(n5562), .Z(n5558));
+ OR2 U5252 ( .A(n5563), .B(n5564), .Z(n5561));
+ AN2 U5253 ( .A(pi055), .B(n3512), .Z(n5564));
+ AN2 U5254 ( .A(n5565), .B(pi124), .Z(n5563));
+ AN2 U5255 ( .A(n5566), .B(n3363), .Z(n5565));
+ AN2 U5256 ( .A(pi109), .B(n4975), .Z(n5556));
+ AN2 U5257 ( .A(n5567), .B(n5568), .Z(n5553));
+ OR2 U5258 ( .A(n5569), .B(n5570), .Z(n5568));
+ OR2 U5259 ( .A(n5571), .B(n5572), .Z(n5570));
+ AN2 U5260 ( .A(n5573), .B(n5566), .Z(n5572));
+ OR2 U5261 ( .A(pi055), .B(n3512), .Z(n5566));
+ AN2 U5262 ( .A(n5574), .B(n3261), .Z(n5573));
+ OR2 U5263 ( .A(n5575), .B(n5576), .Z(n5574));
+ AN2 U5264 ( .A(pi124), .B(n5562), .Z(n5576));
+ OR2 U5265 ( .A(n5577), .B(n5560), .Z(n5562));
+ AN2 U5266 ( .A(n5578), .B(n3380), .Z(n5577));
+ AN2 U5267 ( .A(n5579), .B(n3363), .Z(n5575));
+ OR2 U5268 ( .A(n5580), .B(n5560), .Z(n5579));
+ AN2 U5269 ( .A(n5578), .B(pi186), .Z(n5560));
+ OR2 U5270 ( .A(pi109), .B(n4975), .Z(n5578));
+ AN2 U5271 ( .A(pi109), .B(n3380), .Z(n5580));
+ AN2 U5272 ( .A(n5581), .B(n5582), .Z(n5571));
+ AN2 U5273 ( .A(n4975), .B(n3380), .Z(n5582));
+ AN2 U5274 ( .A(n5583), .B(n3363), .Z(n5581));
+ OR2 U5275 ( .A(n5584), .B(n5585), .Z(n5583));
+ AN2 U5276 ( .A(pi192), .B(n3512), .Z(n5585));
+ AN2 U5277 ( .A(pi055), .B(n3261), .Z(n5584));
+ OR2 U5278 ( .A(n3926), .B(n5586), .Z(n5569));
+ AN2 U5279 ( .A(n5587), .B(n5588), .Z(n5586));
+ AN2 U5280 ( .A(n5589), .B(pi110), .Z(n5588));
+ AN2 U5281 ( .A(pi167), .B(n2837), .Z(n5589));
+ AN2 U5282 ( .A(pi019), .B(pi085), .Z(n5587));
+ AN2 U5283 ( .A(n5590), .B(n5591), .Z(n5567));
+ OR2 U5284 ( .A(pi192), .B(n5592), .Z(n5591));
+ AN2 U5285 ( .A(n5593), .B(n5594), .Z(n5592));
+ OR2 U5286 ( .A(pi164), .B(n3261), .Z(n5594));
+ OR2 U5287 ( .A(n5595), .B(n5596), .Z(n5593));
+ OR2 U5288 ( .A(n5597), .B(n5598), .Z(n5596));
+ AN2 U5289 ( .A(n5599), .B(pi024), .Z(n5598));
+ AN2 U5290 ( .A(pi195), .B(n5600), .Z(n5597));
+ OR2 U5291 ( .A(n5601), .B(n5599), .Z(n5600));
+ AN2 U5292 ( .A(n5602), .B(n5603), .Z(n5599));
+ IV2 U5293 ( .A(n5604), .Z(n5603));
+ AN2 U5294 ( .A(n5605), .B(n5606), .Z(n5604));
+ OR2 U5295 ( .A(n5607), .B(n5608), .Z(n5606));
+ AN2 U5296 ( .A(n5609), .B(n5610), .Z(n5608));
+ OR2 U5297 ( .A(n5611), .B(n4961), .Z(n5610));
+ IV2 U5298 ( .A(pi030), .Z(n4961));
+ AN2 U5299 ( .A(n5612), .B(n3597), .Z(n5611));
+ OR2 U5300 ( .A(n5612), .B(n3597), .Z(n5609));
+ AN2 U5301 ( .A(n4969), .B(n4440), .Z(n5607));
+ OR2 U5302 ( .A(n4440), .B(n4969), .Z(n5605));
+ IV2 U5303 ( .A(pi159), .Z(n4969));
+ AN2 U5304 ( .A(pi024), .B(n5602), .Z(n5601));
+ OR2 U5305 ( .A(pi087), .B(pi130), .Z(n5602));
+ AN2 U5306 ( .A(pi087), .B(pi130), .Z(n5595));
+ OR2 U5307 ( .A(n2837), .B(n5613), .Z(n5590));
+ OR2 U5308 ( .A(n5614), .B(n5615), .Z(n5613));
+ AN2 U5309 ( .A(n5347), .B(n5616), .Z(n5615));
+ AN2 U5310 ( .A(n5617), .B(n4943), .Z(n5614));
+ OR2 U5311 ( .A(n5347), .B(n5616), .Z(n5617));
+ OR2 U5312 ( .A(n5618), .B(n5619), .Z(n5616));
+ OR2 U5313 ( .A(n5620), .B(n5621), .Z(n5619));
+ AN2 U5314 ( .A(n5622), .B(pi099), .Z(n5621));
+ AN2 U5315 ( .A(n5623), .B(n4937), .Z(n5620));
+ OR2 U5316 ( .A(n5624), .B(n5622), .Z(n5623));
+ AN2 U5317 ( .A(n5625), .B(n5626), .Z(n5622));
+ IV2 U5318 ( .A(n5627), .Z(n5626));
+ AN2 U5319 ( .A(n5628), .B(n5629), .Z(n5627));
+ OR2 U5320 ( .A(n5630), .B(n5631), .Z(n5629));
+ AN2 U5321 ( .A(n5632), .B(n5633), .Z(n5631));
+ OR2 U5322 ( .A(po011), .B(n5634), .Z(n5633));
+ AN2 U5323 ( .A(n5612), .B(n5358), .Z(n5634));
+ OR2 U5324 ( .A(n5612), .B(n5358), .Z(n5632));
+ IV2 U5325 ( .A(pi172), .Z(n5358));
+ IV2 U5326 ( .A(po062), .Z(n5612));
+ OR2 U5327 ( .A(n5635), .B(n5636), .Z(po062));
+ AN2 U5328 ( .A(n5637), .B(n2837), .Z(n5636));
+ OR2 U5329 ( .A(n5638), .B(n5639), .Z(n5637));
+ AN2 U5330 ( .A(pi020), .B(pi095), .Z(n5639));
+ AN2 U5331 ( .A(n5640), .B(n5641), .Z(n5638));
+ OR2 U5332 ( .A(pi020), .B(pi095), .Z(n5641));
+ OR2 U5333 ( .A(n5642), .B(n5643), .Z(n5640));
+ AN2 U5334 ( .A(pi151), .B(n5644), .Z(n5643));
+ AN2 U5335 ( .A(pi153), .B(n5645), .Z(n5642));
+ OR2 U5336 ( .A(pi151), .B(n5644), .Z(n5645));
+ OR2 U5337 ( .A(n5646), .B(n5647), .Z(n5644));
+ AN2 U5338 ( .A(pi075), .B(pi156), .Z(n5647));
+ AN2 U5339 ( .A(n5648), .B(n5649), .Z(n5646));
+ OR2 U5340 ( .A(pi075), .B(pi156), .Z(n5649));
+ OR2 U5341 ( .A(n5650), .B(n5651), .Z(n5648));
+ AN2 U5342 ( .A(pi040), .B(n5652), .Z(n5651));
+ AN2 U5343 ( .A(pi047), .B(n5653), .Z(n5650));
+ OR2 U5344 ( .A(pi040), .B(n5652), .Z(n5653));
+ AN2 U5345 ( .A(pi192), .B(n5654), .Z(n5635));
+ OR2 U5346 ( .A(n5655), .B(n5656), .Z(n5654));
+ OR2 U5347 ( .A(n5657), .B(n5658), .Z(n5656));
+ AN2 U5348 ( .A(pi101), .B(n5659), .Z(n5658));
+ AN2 U5349 ( .A(n5660), .B(n4628), .Z(n5657));
+ OR2 U5350 ( .A(n5661), .B(n5659), .Z(n5660));
+ OR2 U5351 ( .A(n5662), .B(n5663), .Z(n5659));
+ AN2 U5352 ( .A(n5664), .B(pi036), .Z(n5663));
+ AN2 U5353 ( .A(n5665), .B(n4861), .Z(n5662));
+ OR2 U5354 ( .A(n5666), .B(n5664), .Z(n5665));
+ AN2 U5355 ( .A(n5667), .B(n5668), .Z(n5664));
+ IV2 U5356 ( .A(n5669), .Z(n5668));
+ AN2 U5357 ( .A(n5670), .B(n5671), .Z(n5669));
+ OR2 U5358 ( .A(po039), .B(n5672), .Z(n5671));
+ AN2 U5359 ( .A(n5673), .B(n5331), .Z(n5672));
+ OR2 U5360 ( .A(n5673), .B(n5331), .Z(n5670));
+ IV2 U5361 ( .A(pi168), .Z(n5331));
+ IV2 U5362 ( .A(n5652), .Z(n5673));
+ OR2 U5363 ( .A(n5674), .B(n5675), .Z(n5652));
+ AN2 U5364 ( .A(n5676), .B(n2837), .Z(n5675));
+ OR2 U5365 ( .A(n5677), .B(n5678), .Z(n5676));
+ AN2 U5366 ( .A(pi143), .B(pi108), .Z(n5678));
+ AN2 U5367 ( .A(n5679), .B(n5680), .Z(n5677));
+ OR2 U5368 ( .A(pi108), .B(pi143), .Z(n5680));
+ OR2 U5369 ( .A(n5681), .B(n5682), .Z(n5679));
+ AN2 U5370 ( .A(pi014), .B(pi114), .Z(n5682));
+ AN2 U5371 ( .A(n5683), .B(n5684), .Z(n5681));
+ OR2 U5372 ( .A(pi014), .B(pi114), .Z(n5684));
+ OR2 U5373 ( .A(n5685), .B(n5686), .Z(n5683));
+ OR2 U5374 ( .A(n5687), .B(n5688), .Z(n5686));
+ AN2 U5375 ( .A(n5689), .B(pi170), .Z(n5688));
+ AN2 U5376 ( .A(pi176), .B(n5690), .Z(n5687));
+ OR2 U5377 ( .A(n5691), .B(n5689), .Z(n5690));
+ AN2 U5378 ( .A(n5692), .B(n5693), .Z(n5689));
+ IV2 U5379 ( .A(n5694), .Z(n5693));
+ AN2 U5380 ( .A(n5695), .B(n5696), .Z(n5694));
+ OR2 U5381 ( .A(n5697), .B(n4899), .Z(n5696));
+ IV2 U5382 ( .A(pi097), .Z(n4899));
+ AN2 U5383 ( .A(n5698), .B(n4077), .Z(n5697));
+ OR2 U5384 ( .A(n5698), .B(n4077), .Z(n5695));
+ AN2 U5385 ( .A(pi170), .B(n5692), .Z(n5691));
+ OR2 U5386 ( .A(pi160), .B(pi189), .Z(n5692));
+ AN2 U5387 ( .A(pi189), .B(pi160), .Z(n5685));
+ AN2 U5388 ( .A(pi192), .B(n5699), .Z(n5674));
+ OR2 U5389 ( .A(n5700), .B(n5701), .Z(n5699));
+ AN2 U5390 ( .A(pi089), .B(n4881), .Z(n5701));
+ AN2 U5391 ( .A(n5702), .B(n5703), .Z(n5700));
+ OR2 U5392 ( .A(pi089), .B(n4881), .Z(n5703));
+ OR2 U5393 ( .A(n5704), .B(n5705), .Z(n5702));
+ AN2 U5394 ( .A(pi027), .B(n4885), .Z(n5705));
+ AN2 U5395 ( .A(n5706), .B(n5707), .Z(n5704));
+ OR2 U5396 ( .A(pi027), .B(n4885), .Z(n5707));
+ OR2 U5397 ( .A(n5708), .B(n5709), .Z(n5706));
+ OR2 U5398 ( .A(n5710), .B(n5711), .Z(n5709));
+ AN2 U5399 ( .A(n5712), .B(pi083), .Z(n5711));
+ AN2 U5400 ( .A(n5713), .B(n4877), .Z(n5710));
+ OR2 U5401 ( .A(n5714), .B(n5712), .Z(n5713));
+ AN2 U5402 ( .A(n5715), .B(n5716), .Z(n5712));
+ IV2 U5403 ( .A(n5717), .Z(n5716));
+ AN2 U5404 ( .A(n5718), .B(n5719), .Z(n5717));
+ OR2 U5405 ( .A(po025), .B(n5720), .Z(n5719));
+ AN2 U5406 ( .A(n5698), .B(n5303), .Z(n5720));
+ OR2 U5407 ( .A(n5698), .B(n5303), .Z(n5718));
+ IV2 U5408 ( .A(pi140), .Z(n5303));
+ IV2 U5409 ( .A(n5721), .Z(n5698));
+ OR2 U5410 ( .A(n5722), .B(n5723), .Z(n5721));
+ AN2 U5411 ( .A(n5724), .B(n2837), .Z(n5723));
+ OR2 U5412 ( .A(n5725), .B(n5726), .Z(n5724));
+ OR2 U5413 ( .A(n5727), .B(n5728), .Z(n5726));
+ AN2 U5414 ( .A(n5729), .B(pi094), .Z(n5728));
+ AN2 U5415 ( .A(pi128), .B(n5730), .Z(n5727));
+ OR2 U5416 ( .A(n5731), .B(n5729), .Z(n5730));
+ AN2 U5417 ( .A(n5732), .B(n5733), .Z(n5729));
+ IV2 U5418 ( .A(n5734), .Z(n5733));
+ AN2 U5419 ( .A(n5735), .B(n5736), .Z(n5734));
+ OR2 U5420 ( .A(n5737), .B(n5738), .Z(n5736));
+ AN2 U5421 ( .A(n5739), .B(n5740), .Z(n5738));
+ OR2 U5422 ( .A(n5741), .B(n5115), .Z(n5740));
+ AN2 U5423 ( .A(n5742), .B(n4778), .Z(n5741));
+ OR2 U5424 ( .A(n5742), .B(n4778), .Z(n5739));
+ IV2 U5425 ( .A(pi163), .Z(n4778));
+ AN2 U5426 ( .A(n3177), .B(n4770), .Z(n5737));
+ OR2 U5427 ( .A(n3177), .B(n4770), .Z(n5735));
+ IV2 U5428 ( .A(pi028), .Z(n4770));
+ AN2 U5429 ( .A(pi094), .B(n5732), .Z(n5731));
+ OR2 U5430 ( .A(pi173), .B(pi185), .Z(n5732));
+ AN2 U5431 ( .A(pi173), .B(pi185), .Z(n5725));
+ AN2 U5432 ( .A(pi192), .B(n5743), .Z(n5722));
+ OR2 U5433 ( .A(n5744), .B(n5745), .Z(n5743));
+ OR2 U5434 ( .A(n5746), .B(n5747), .Z(n5745));
+ AN2 U5435 ( .A(pi131), .B(n5748), .Z(n5747));
+ AN2 U5436 ( .A(n5749), .B(n5040), .Z(n5746));
+ OR2 U5437 ( .A(n5750), .B(n5748), .Z(n5749));
+ OR2 U5438 ( .A(n5751), .B(n5752), .Z(n5748));
+ AN2 U5439 ( .A(n5753), .B(pi059), .Z(n5752));
+ AN2 U5440 ( .A(n5754), .B(n3286), .Z(n5751));
+ OR2 U5441 ( .A(n5755), .B(n5753), .Z(n5754));
+ AN2 U5442 ( .A(n5756), .B(n5757), .Z(n5753));
+ IV2 U5443 ( .A(n5758), .Z(n5757));
+ AN2 U5444 ( .A(n5759), .B(n5760), .Z(n5758));
+ OR2 U5445 ( .A(po010), .B(n5761), .Z(n5760));
+ AN2 U5446 ( .A(n5742), .B(n5439), .Z(n5761));
+ OR2 U5447 ( .A(n5742), .B(n5439), .Z(n5759));
+ IV2 U5448 ( .A(pi197), .Z(n5439));
+ IV2 U5449 ( .A(n5762), .Z(n5742));
+ OR2 U5450 ( .A(n5763), .B(n5764), .Z(n5762));
+ AN2 U5451 ( .A(n5765), .B(n2837), .Z(n5764));
+ OR2 U5452 ( .A(n5766), .B(n5767), .Z(n5765));
+ AN2 U5453 ( .A(pi021), .B(pi201), .Z(n5767));
+ AN2 U5454 ( .A(n5768), .B(n5769), .Z(n5766));
+ OR2 U5455 ( .A(pi021), .B(pi201), .Z(n5769));
+ OR2 U5456 ( .A(n5770), .B(n5771), .Z(n5768));
+ IV2 U5457 ( .A(n5772), .Z(n5771));
+ AN2 U5458 ( .A(n5773), .B(n5774), .Z(n5772));
+ OR2 U5459 ( .A(n5775), .B(n5022), .Z(n5774));
+ OR2 U5460 ( .A(n5431), .B(n5776), .Z(n5773));
+ AN2 U5461 ( .A(n5777), .B(n5775), .Z(n5776));
+ OR2 U5462 ( .A(n5778), .B(n5779), .Z(n5775));
+ AN2 U5463 ( .A(n5780), .B(n5781), .Z(n5779));
+ OR2 U5464 ( .A(n5782), .B(n5783), .Z(n5781));
+ AN2 U5465 ( .A(n5784), .B(n5785), .Z(n5783));
+ OR2 U5466 ( .A(n5786), .B(n5787), .Z(n5785));
+ IV2 U5467 ( .A(pi181), .Z(n5787));
+ AN2 U5468 ( .A(n2982), .B(n5019), .Z(n5786));
+ OR2 U5469 ( .A(n2982), .B(n5019), .Z(n5784));
+ IV2 U5470 ( .A(pi011), .Z(n5019));
+ AN2 U5471 ( .A(n5027), .B(n2957), .Z(n5782));
+ OR2 U5472 ( .A(n2957), .B(n5027), .Z(n5780));
+ IV2 U5473 ( .A(pi086), .Z(n5027));
+ OR2 U5474 ( .A(n5022), .B(n5778), .Z(n5777));
+ AN2 U5475 ( .A(n5165), .B(n5031), .Z(n5778));
+ IV2 U5476 ( .A(pi165), .Z(n5031));
+ IV2 U5477 ( .A(pi032), .Z(n5022));
+ AN2 U5478 ( .A(pi165), .B(pi107), .Z(n5770));
+ AN2 U5479 ( .A(pi192), .B(n5788), .Z(n5763));
+ OR2 U5480 ( .A(n5789), .B(n5790), .Z(n5788));
+ AN2 U5481 ( .A(pi121), .B(n5000), .Z(n5790));
+ AN2 U5482 ( .A(n5791), .B(n5792), .Z(n5789));
+ OR2 U5483 ( .A(pi121), .B(n5000), .Z(n5792));
+ OR2 U5484 ( .A(n5793), .B(n5794), .Z(n5791));
+ AN2 U5485 ( .A(pi053), .B(n5795), .Z(n5794));
+ AN2 U5486 ( .A(n5796), .B(n5004), .Z(n5793));
+ OR2 U5487 ( .A(pi053), .B(n5795), .Z(n5796));
+ OR2 U5488 ( .A(n5797), .B(n5798), .Z(n5795));
+ AN2 U5489 ( .A(pi184), .B(n5008), .Z(n5798));
+ AN2 U5490 ( .A(n5799), .B(n5800), .Z(n5797));
+ OR2 U5491 ( .A(pi184), .B(n5008), .Z(n5800));
+ OR2 U5492 ( .A(n5801), .B(n5802), .Z(n5799));
+ AN2 U5493 ( .A(pi181), .B(pi103), .Z(n5802));
+ AN2 U5494 ( .A(n5803), .B(n2962), .Z(n5801));
+ OR2 U5495 ( .A(pi103), .B(pi181), .Z(n5803));
+ AN2 U5496 ( .A(pi059), .B(n5756), .Z(n5755));
+ AN2 U5497 ( .A(pi131), .B(n5756), .Z(n5750));
+ OR2 U5498 ( .A(pi001), .B(n5037), .Z(n5756));
+ AN2 U5499 ( .A(pi001), .B(n5037), .Z(n5744));
+ AN2 U5500 ( .A(pi083), .B(n5715), .Z(n5714));
+ OR2 U5501 ( .A(pi162), .B(n4874), .Z(n5715));
+ AN2 U5502 ( .A(pi162), .B(n4874), .Z(n5708));
+ AN2 U5503 ( .A(pi036), .B(n5667), .Z(n5666));
+ AN2 U5504 ( .A(pi101), .B(n5667), .Z(n5661));
+ OR2 U5505 ( .A(pi205), .B(n4915), .Z(n5667));
+ AN2 U5506 ( .A(pi205), .B(n4915), .Z(n5655));
+ AN2 U5507 ( .A(po036), .B(n5350), .Z(n5630));
+ OR2 U5508 ( .A(po036), .B(n5350), .Z(n5628));
+ IV2 U5509 ( .A(pi018), .Z(n5350));
+ AN2 U5510 ( .A(pi099), .B(n5625), .Z(n5624));
+ OR2 U5511 ( .A(pi180), .B(n4947), .Z(n5625));
+ AN2 U5512 ( .A(pi180), .B(n4947), .Z(n5618));
+ AN2 U5513 ( .A(n3261), .B(pi049), .Z(n5347));
+ AN2 U5514 ( .A(n3926), .B(n5804), .Z(n5551));
+ OR2 U5515 ( .A(n5805), .B(n5806), .Z(n5804));
+ OR2 U5516 ( .A(pi085), .B(pi019), .Z(n5806));
+ OR2 U5517 ( .A(pi110), .B(n5807), .Z(n5805));
+ OR2 U5518 ( .A(pi167), .B(pi164), .Z(n5807));
+ AN2 U5519 ( .A(pi126), .B(pi190), .Z(n5549));
+ AN2 U5520 ( .A(n5808), .B(pi035), .Z(n5547));
+ AN2 U5521 ( .A(pi056), .B(pi100), .Z(n5808));
+ AN2 U5522 ( .A(pi054), .B(n5809), .Z(n5504));
+ OR2 U5523 ( .A(n4167), .B(n5810), .Z(n5809));
+ OR2 U5524 ( .A(pi146), .B(pi025), .Z(n5810));
+ AN2 U5525 ( .A(n5811), .B(n2882), .Z(po017));
+ OR2 U5526 ( .A(pi200), .B(n3003), .Z(n5811));
+ OR2 U5527 ( .A(n5812), .B(n5813), .Z(po016));
+ OR2 U5528 ( .A(n5814), .B(n5815), .Z(n5813));
+ AN2 U5529 ( .A(n3280), .B(n3064), .Z(n5815));
+ AN2 U5530 ( .A(n5100), .B(n5816), .Z(n5814));
+ OR2 U5531 ( .A(n5817), .B(n5818), .Z(n5816));
+ AN2 U5532 ( .A(n3055), .B(n5819), .Z(n5818));
+ OR2 U5533 ( .A(n2845), .B(n3143), .Z(n5819));
+ OR2 U5534 ( .A(n2978), .B(n3147), .Z(n3143));
+ AN2 U5535 ( .A(n3127), .B(n5820), .Z(n5817));
+ OR2 U5536 ( .A(n2833), .B(n3138), .Z(n5820));
+ OR2 U5537 ( .A(n2880), .B(n3147), .Z(n3138));
+ OR2 U5538 ( .A(n2998), .B(n5821), .Z(n3147));
+ OR2 U5539 ( .A(n2882), .B(n2862), .Z(n5821));
+ OR2 U5540 ( .A(n2925), .B(n2901), .Z(n2882));
+ AN2 U5541 ( .A(pi192), .B(n3036), .Z(n3127));
+ IV2 U5542 ( .A(n5822), .Z(n5100));
+ OR2 U5543 ( .A(n5823), .B(n5824), .Z(n5812));
+ AN2 U5544 ( .A(n5825), .B(pi192), .Z(n5824));
+ AN2 U5545 ( .A(n5826), .B(po010), .Z(n5825));
+ AN2 U5546 ( .A(n5827), .B(n2837), .Z(n5823));
+ AN2 U5547 ( .A(n5828), .B(n5829), .Z(n5827));
+ OR2 U5548 ( .A(n5830), .B(n5831), .Z(po008));
+ AN2 U5549 ( .A(n3344), .B(n3251), .Z(n5831));
+ OR2 U5550 ( .A(n5832), .B(n5833), .Z(n3251));
+ AN2 U5551 ( .A(n3355), .B(n5454), .Z(n5832));
+ OR2 U5552 ( .A(n5834), .B(n5835), .Z(n5454));
+ AN2 U5553 ( .A(n5836), .B(n4426), .Z(n5834));
+ IV2 U5554 ( .A(n3352), .Z(n3355));
+ AN2 U5555 ( .A(n3250), .B(n5837), .Z(n5830));
+ OR2 U5556 ( .A(n5838), .B(n5839), .Z(n5837));
+ OR2 U5557 ( .A(n5840), .B(n3245), .Z(n5839));
+ OR2 U5558 ( .A(n5841), .B(n5842), .Z(n3245));
+ AN2 U5559 ( .A(n3244), .B(n3699), .Z(n5842));
+ AN2 U5560 ( .A(n3242), .B(n3700), .Z(n5841));
+ IV2 U5561 ( .A(n5843), .Z(n3242));
+ AN2 U5562 ( .A(n3352), .B(n3701), .Z(n5840));
+ OR2 U5563 ( .A(n5844), .B(n5845), .Z(n5838));
+ AN2 U5564 ( .A(n4418), .B(n3762), .Z(n5845));
+ AN2 U5565 ( .A(n5846), .B(n3236), .Z(n5844));
+ OR2 U5566 ( .A(pi037), .B(n5847), .Z(po007));
+ IV2 U5567 ( .A(pi116), .Z(n5847));
+ OR2 U5568 ( .A(n5848), .B(n5849), .Z(po006));
+ AN2 U5569 ( .A(n3370), .B(n5850), .Z(n5849));
+ OR2 U5570 ( .A(n5851), .B(n5852), .Z(n5850));
+ OR2 U5571 ( .A(n5853), .B(n5138), .Z(n5852));
+ OR2 U5572 ( .A(n5854), .B(n3566), .Z(n5138));
+ AN2 U5573 ( .A(n3512), .B(n3926), .Z(n3566));
+ AN2 U5574 ( .A(n3926), .B(n4368), .Z(n5854));
+ OR2 U5575 ( .A(n5855), .B(n5856), .Z(n5851));
+ AN2 U5576 ( .A(n5139), .B(n3380), .Z(n5856));
+ OR2 U5577 ( .A(n5857), .B(n5858), .Z(n5139));
+ AN2 U5578 ( .A(n5859), .B(n3261), .Z(n5857));
+ AN2 U5579 ( .A(n5860), .B(pi118), .Z(n5855));
+ AN2 U5580 ( .A(n5861), .B(n3261), .Z(n5860));
+ OR2 U5581 ( .A(n5858), .B(n5859), .Z(n5861));
+ OR2 U5582 ( .A(n5862), .B(n5863), .Z(n5859));
+ OR2 U5583 ( .A(n3404), .B(n5864), .Z(n5863));
+ AN2 U5584 ( .A(n5865), .B(pi060), .Z(n5864));
+ AN2 U5585 ( .A(n4368), .B(n5866), .Z(n5865));
+ IV2 U5586 ( .A(n3446), .Z(n3404));
+ AN2 U5587 ( .A(n4367), .B(pi196), .Z(n5862));
+ IV2 U5588 ( .A(n4364), .Z(n4367));
+ IV2 U5589 ( .A(n5867), .Z(n5858));
+ IV2 U5590 ( .A(n3393), .Z(n3370));
+ AN2 U5591 ( .A(n3393), .B(n5868), .Z(n5848));
+ OR2 U5592 ( .A(n5869), .B(n5870), .Z(n5868));
+ OR2 U5593 ( .A(n5135), .B(n5871), .Z(n5870));
+ AN2 U5594 ( .A(n3480), .B(n5872), .Z(n5871));
+ AN2 U5595 ( .A(n5867), .B(n3321), .Z(n5135));
+ OR2 U5596 ( .A(po104), .B(n4364), .Z(n5867));
+ OR2 U5597 ( .A(n5873), .B(n5874), .Z(n5869));
+ OR2 U5598 ( .A(n5875), .B(n5876), .Z(n5874));
+ AN2 U5599 ( .A(n5877), .B(po071), .Z(n5876));
+ OR2 U5600 ( .A(n5136), .B(n5878), .Z(n5877));
+ OR2 U5601 ( .A(n5879), .B(n5880), .Z(n5136));
+ OR2 U5602 ( .A(n5881), .B(n5882), .Z(n5880));
+ AN2 U5603 ( .A(n3398), .B(n4364), .Z(n5882));
+ AN2 U5604 ( .A(n4363), .B(n3419), .Z(n5879));
+ AN2 U5605 ( .A(n5883), .B(n3398), .Z(n5875));
+ AN2 U5606 ( .A(n3446), .B(n3533), .Z(n3398));
+ AN2 U5607 ( .A(n4364), .B(n3913), .Z(n5883));
+ OR2 U5608 ( .A(n4062), .B(po027), .Z(n4364));
+ IV2 U5609 ( .A(n4061), .Z(n4062));
+ AN2 U5610 ( .A(n3416), .B(n4363), .Z(n5873));
+ IV2 U5611 ( .A(n4368), .Z(n4363));
+ OR2 U5612 ( .A(n3363), .B(n4061), .Z(n4368));
+ OR2 U5613 ( .A(n5884), .B(n5885), .Z(n4061));
+ OR2 U5614 ( .A(n5886), .B(n5887), .Z(n5885));
+ AN2 U5615 ( .A(n5888), .B(n4943), .Z(n5887));
+ AN2 U5616 ( .A(n5889), .B(n3989), .Z(n5886));
+ OR2 U5617 ( .A(n5890), .B(n5891), .Z(n5884));
+ OR2 U5618 ( .A(n5892), .B(n3490), .Z(n5891));
+ AN2 U5619 ( .A(n5893), .B(n5894), .Z(n5890));
+ AN2 U5620 ( .A(n3495), .B(n5895), .Z(n5893));
+ AN2 U5621 ( .A(n3446), .B(n3480), .Z(n3416));
+ OR2 U5622 ( .A(po104), .B(n3942), .Z(n3446));
+ OR2 U5623 ( .A(n5896), .B(n3253), .Z(po012));
+ AN2 U5624 ( .A(n5897), .B(pi054), .Z(n3253));
+ OR2 U5625 ( .A(n4133), .B(n5898), .Z(n5897));
+ AN2 U5626 ( .A(n4127), .B(n3255), .Z(n5896));
+ OR2 U5627 ( .A(pi054), .B(n5120), .Z(n3255));
+ OR2 U5628 ( .A(n5899), .B(n4167), .Z(n5120));
+ AN2 U5629 ( .A(n4133), .B(n4128), .Z(n5899));
+ IV2 U5630 ( .A(po064), .Z(n4133));
+ OR2 U5631 ( .A(n5900), .B(n4372), .Z(n4127));
+ OR2 U5632 ( .A(n5901), .B(n5902), .Z(n4372));
+ AN2 U5633 ( .A(n4380), .B(n4319), .Z(n5901));
+ AN2 U5634 ( .A(n5903), .B(n4374), .Z(n5900));
+ OR2 U5635 ( .A(n5904), .B(n5905), .Z(n4374));
+ AN2 U5636 ( .A(n5906), .B(n3261), .Z(n5905));
+ OR2 U5637 ( .A(n5907), .B(n5908), .Z(n5906));
+ OR2 U5638 ( .A(n5909), .B(n5910), .Z(n5908));
+ AN2 U5639 ( .A(n5911), .B(po103), .Z(n5910));
+ AN2 U5640 ( .A(n5912), .B(pi058), .Z(n5911));
+ AN2 U5641 ( .A(n5913), .B(n5914), .Z(n5912));
+ AN2 U5642 ( .A(n5915), .B(n5916), .Z(n5913));
+ OR2 U5643 ( .A(pi204), .B(n5917), .Z(n5916));
+ AN2 U5644 ( .A(n4057), .B(n4013), .Z(n5917));
+ OR2 U5645 ( .A(n5918), .B(n5919), .Z(n5915));
+ AN2 U5646 ( .A(po040), .B(n3966), .Z(n5918));
+ AN2 U5647 ( .A(n5920), .B(n3265), .Z(n5909));
+ AN2 U5648 ( .A(n5921), .B(n5922), .Z(n5920));
+ AN2 U5649 ( .A(n4057), .B(n4316), .Z(n5922));
+ AN2 U5650 ( .A(n4157), .B(n5914), .Z(n5921));
+ OR2 U5651 ( .A(n5923), .B(n4319), .Z(n5914));
+ AN2 U5652 ( .A(pi065), .B(pi192), .Z(n5923));
+ OR2 U5653 ( .A(pi204), .B(n4013), .Z(n4157));
+ AN2 U5654 ( .A(n5924), .B(n4046), .Z(n5907));
+ AN2 U5655 ( .A(po040), .B(n3263), .Z(n5924));
+ OR2 U5656 ( .A(n5925), .B(n2837), .Z(n3263));
+ AN2 U5657 ( .A(n3264), .B(pi058), .Z(n5925));
+ AN2 U5658 ( .A(n4391), .B(n4319), .Z(n5904));
+ AN2 U5659 ( .A(n3265), .B(n4013), .Z(n4391));
+ IV2 U5660 ( .A(n4158), .Z(n5903));
+ OR2 U5661 ( .A(n4312), .B(n5926), .Z(n4158));
+ OR2 U5662 ( .A(n4040), .B(n4229), .Z(n5926));
+ IV2 U5663 ( .A(n4184), .Z(n4229));
+ OR2 U5664 ( .A(n5927), .B(n5928), .Z(n4184));
+ OR2 U5665 ( .A(n5929), .B(n5930), .Z(n5928));
+ AN2 U5666 ( .A(n5931), .B(n5932), .Z(n5929));
+ OR2 U5667 ( .A(n5933), .B(n5934), .Z(n5932));
+ AN2 U5668 ( .A(n3457), .B(n3493), .Z(n5934));
+ IV2 U5669 ( .A(n3661), .Z(n3493));
+ OR2 U5670 ( .A(n5935), .B(n5936), .Z(n3661));
+ OR2 U5671 ( .A(n3229), .B(n3235), .Z(n5936));
+ OR2 U5672 ( .A(n5937), .B(n5938), .Z(n3235));
+ OR2 U5673 ( .A(n5939), .B(n5940), .Z(n5938));
+ AN2 U5674 ( .A(n5452), .B(n3241), .Z(n5940));
+ AN2 U5675 ( .A(n5453), .B(n3243), .Z(n5939));
+ AN2 U5676 ( .A(po082), .B(n5846), .Z(n5937));
+ OR2 U5677 ( .A(n5941), .B(n5942), .Z(n5846));
+ AN2 U5678 ( .A(n5452), .B(n3700), .Z(n5942));
+ AN2 U5679 ( .A(n3638), .B(n3635), .Z(n5452));
+ IV2 U5680 ( .A(pi098), .Z(n3638));
+ AN2 U5681 ( .A(n5453), .B(n3699), .Z(n5941));
+ AN2 U5682 ( .A(n3597), .B(n3593), .Z(n5453));
+ OR2 U5683 ( .A(n5943), .B(n5944), .Z(n3229));
+ AN2 U5684 ( .A(po082), .B(n3344), .Z(n5944));
+ AN2 U5685 ( .A(n3352), .B(n5945), .Z(n5943));
+ OR2 U5686 ( .A(n5946), .B(n5947), .Z(n5945));
+ OR2 U5687 ( .A(n3241), .B(n3243), .Z(n5947));
+ AN2 U5688 ( .A(po082), .B(n3701), .Z(n5946));
+ IV2 U5689 ( .A(n5833), .Z(n3701));
+ OR2 U5690 ( .A(n3233), .B(n5948), .Z(n5935));
+ AN2 U5691 ( .A(n3339), .B(n5949), .Z(n5948));
+ AN2 U5692 ( .A(n5949), .B(po011), .Z(n3233));
+ OR2 U5693 ( .A(n5950), .B(n5951), .Z(n5949));
+ OR2 U5694 ( .A(n5952), .B(n5953), .Z(n5951));
+ AN2 U5695 ( .A(n3241), .B(n3635), .Z(n5953));
+ AN2 U5696 ( .A(n3992), .B(n3700), .Z(n3241));
+ AN2 U5697 ( .A(n3632), .B(pi192), .Z(n3700));
+ IV2 U5698 ( .A(pi004), .Z(n3992));
+ AN2 U5699 ( .A(n3243), .B(n3593), .Z(n5952));
+ OR2 U5700 ( .A(po036), .B(n4440), .Z(n3593));
+ AN2 U5701 ( .A(n5372), .B(n3699), .Z(n3243));
+ AN2 U5702 ( .A(po082), .B(n3762), .Z(n5950));
+ OR2 U5703 ( .A(n5954), .B(n5955), .Z(n3762));
+ OR2 U5704 ( .A(n5956), .B(n5957), .Z(n5955));
+ AN2 U5705 ( .A(po036), .B(n5958), .Z(n5957));
+ OR2 U5706 ( .A(n5959), .B(po001), .Z(n5958));
+ AN2 U5707 ( .A(pi192), .B(n5960), .Z(n5956));
+ OR2 U5708 ( .A(n5961), .B(n5962), .Z(n5960));
+ AN2 U5709 ( .A(po001), .B(n4001), .Z(n5962));
+ AN2 U5710 ( .A(n3635), .B(n3998), .Z(n5961));
+ OR2 U5711 ( .A(po036), .B(n4001), .Z(n3635));
+ IV2 U5712 ( .A(pi171), .Z(n4001));
+ AN2 U5713 ( .A(n3699), .B(n4440), .Z(n5954));
+ AN2 U5714 ( .A(n2837), .B(n3590), .Z(n3699));
+ AN2 U5715 ( .A(n5963), .B(n3667), .Z(n5933));
+ AN2 U5716 ( .A(n3291), .B(n3341), .Z(n3667));
+ IV2 U5717 ( .A(n3339), .Z(n3341));
+ OR2 U5718 ( .A(n5964), .B(n5965), .Z(n3339));
+ AN2 U5719 ( .A(n5966), .B(n4441), .Z(n5965));
+ AN2 U5720 ( .A(n5448), .B(po036), .Z(n5964));
+ IV2 U5721 ( .A(n5966), .Z(n5448));
+ OR2 U5722 ( .A(n5967), .B(n5968), .Z(n3291));
+ AN2 U5723 ( .A(n5969), .B(n3688), .Z(n5968));
+ IV2 U5724 ( .A(n3746), .Z(n5969));
+ AN2 U5725 ( .A(po011), .B(n3746), .Z(n5967));
+ OR2 U5726 ( .A(n3717), .B(n3705), .Z(n3746));
+ AN2 U5727 ( .A(n3495), .B(n5970), .Z(n5963));
+ OR2 U5728 ( .A(n5971), .B(n5972), .Z(n5970));
+ OR2 U5729 ( .A(n5973), .B(n5974), .Z(n5972));
+ AN2 U5730 ( .A(n5975), .B(pi192), .Z(n5974));
+ AN2 U5731 ( .A(n3567), .B(n5976), .Z(n5975));
+ OR2 U5732 ( .A(n5977), .B(n5978), .Z(n5976));
+ OR2 U5733 ( .A(n5979), .B(n5980), .Z(n5978));
+ AN2 U5734 ( .A(n4635), .B(n5981), .Z(n5979));
+ IV2 U5735 ( .A(n4464), .Z(n4635));
+ OR2 U5736 ( .A(po039), .B(n3870), .Z(n4464));
+ IV2 U5737 ( .A(pi016), .Z(n3870));
+ OR2 U5738 ( .A(n5982), .B(n5983), .Z(n5977));
+ AN2 U5739 ( .A(n5984), .B(n3033), .Z(n5983));
+ IV2 U5740 ( .A(n3038), .Z(n3033));
+ OR2 U5741 ( .A(po070), .B(n3199), .Z(n3038));
+ IV2 U5742 ( .A(pi096), .Z(n3199));
+ AN2 U5743 ( .A(n5985), .B(n5986), .Z(n5982));
+ OR2 U5744 ( .A(n5987), .B(n3042), .Z(n5986));
+ IV2 U5745 ( .A(n3037), .Z(n3042));
+ OR2 U5746 ( .A(po099), .B(n3171), .Z(n3037));
+ AN2 U5747 ( .A(n3063), .B(n5988), .Z(n5987));
+ OR2 U5748 ( .A(n5989), .B(n5990), .Z(n5988));
+ AN2 U5749 ( .A(n3036), .B(n5991), .Z(n5989));
+ OR2 U5750 ( .A(n5992), .B(n3010), .Z(n5991));
+ OR2 U5751 ( .A(n5993), .B(n5994), .Z(n3010));
+ AN2 U5752 ( .A(pi088), .B(n3012), .Z(n5992));
+ IV2 U5753 ( .A(n5995), .Z(n3036));
+ OR2 U5754 ( .A(n5996), .B(n5990), .Z(n5995));
+ AN2 U5755 ( .A(pi166), .B(n3049), .Z(n5990));
+ AN2 U5756 ( .A(po010), .B(n3106), .Z(n5996));
+ OR2 U5757 ( .A(n3534), .B(n3363), .Z(n3567));
+ AN2 U5758 ( .A(n5997), .B(n3457), .Z(n5973));
+ IV2 U5759 ( .A(n4060), .Z(n3457));
+ OR2 U5760 ( .A(n5998), .B(n5999), .Z(n4060));
+ AN2 U5761 ( .A(po027), .B(n3451), .Z(n5998));
+ AN2 U5762 ( .A(n3760), .B(n4652), .Z(n5997));
+ AN2 U5763 ( .A(n6000), .B(n6001), .Z(n5971));
+ OR2 U5764 ( .A(n3261), .B(n3525), .Z(n6001));
+ AN2 U5765 ( .A(n3363), .B(n3321), .Z(n3525));
+ OR2 U5766 ( .A(n6002), .B(n6003), .Z(n6000));
+ AN2 U5767 ( .A(n6004), .B(n2837), .Z(n6003));
+ OR2 U5768 ( .A(n6005), .B(n6006), .Z(n6004));
+ OR2 U5769 ( .A(n6007), .B(n6008), .Z(n6006));
+ AN2 U5770 ( .A(n4641), .B(n5981), .Z(n6007));
+ IV2 U5771 ( .A(n4468), .Z(n4641));
+ OR2 U5772 ( .A(po039), .B(n4735), .Z(n4468));
+ IV2 U5773 ( .A(pi040), .Z(n4735));
+ OR2 U5774 ( .A(n6009), .B(n6010), .Z(n6005));
+ AN2 U5775 ( .A(n5985), .B(n6011), .Z(n6010));
+ OR2 U5776 ( .A(n6012), .B(n6013), .Z(n6011));
+ OR2 U5777 ( .A(n3066), .B(n6014), .Z(n6013));
+ AN2 U5778 ( .A(n6015), .B(n6016), .Z(n6014));
+ IV2 U5779 ( .A(n3112), .Z(n3066));
+ OR2 U5780 ( .A(po099), .B(n3177), .Z(n3112));
+ AN2 U5781 ( .A(n6017), .B(n6018), .Z(n6012));
+ OR2 U5782 ( .A(n6019), .B(n6020), .Z(n6018));
+ AN2 U5783 ( .A(n6021), .B(n3119), .Z(n6019));
+ OR2 U5784 ( .A(n6022), .B(n5993), .Z(n6021));
+ AN2 U5785 ( .A(n2890), .B(n5000), .Z(n5993));
+ AN2 U5786 ( .A(pi201), .B(n3012), .Z(n6022));
+ OR2 U5787 ( .A(n2890), .B(n5000), .Z(n3012));
+ IV2 U5788 ( .A(n2886), .Z(n2890));
+ OR2 U5789 ( .A(n6023), .B(n6024), .Z(n2886));
+ OR2 U5790 ( .A(n6025), .B(n6026), .Z(n6024));
+ AN2 U5791 ( .A(n6027), .B(n2998), .Z(n6026));
+ AN2 U5792 ( .A(po079), .B(n6028), .Z(n6025));
+ OR2 U5793 ( .A(n6029), .B(n4095), .Z(n6028));
+ OR2 U5794 ( .A(n6030), .B(n6031), .Z(n4095));
+ AN2 U5795 ( .A(n4098), .B(n2887), .Z(n6031));
+ AN2 U5796 ( .A(n6032), .B(po031), .Z(n6030));
+ AN2 U5797 ( .A(n2990), .B(n2974), .Z(n6032));
+ AN2 U5798 ( .A(n2990), .B(n5169), .Z(n6029));
+ OR2 U5799 ( .A(n6033), .B(po106), .Z(n2990));
+ AN2 U5800 ( .A(n2837), .B(n5431), .Z(n6033));
+ OR2 U5801 ( .A(n6034), .B(n6035), .Z(n6023));
+ AN2 U5802 ( .A(n4099), .B(n6036), .Z(n6035));
+ OR2 U5803 ( .A(n6037), .B(n6038), .Z(n6036));
+ AN2 U5804 ( .A(n6039), .B(n5165), .Z(n6038));
+ OR2 U5805 ( .A(n6040), .B(n5169), .Z(n6039));
+ OR2 U5806 ( .A(n2978), .B(n2862), .Z(n5169));
+ AN2 U5807 ( .A(po031), .B(n2974), .Z(n6040));
+ AN2 U5808 ( .A(n6041), .B(n2974), .Z(n6037));
+ AN2 U5809 ( .A(n5172), .B(n2957), .Z(n6041));
+ AN2 U5810 ( .A(n2947), .B(n2837), .Z(n4099));
+ AN2 U5811 ( .A(n6042), .B(n4098), .Z(n6034));
+ AN2 U5812 ( .A(n2891), .B(pi192), .Z(n4098));
+ IV2 U5813 ( .A(n2892), .Z(n2891));
+ AN2 U5814 ( .A(n6043), .B(n3847), .Z(n6042));
+ IV2 U5815 ( .A(n2885), .Z(n6043));
+ AN2 U5816 ( .A(n5984), .B(n3076), .Z(n6009));
+ IV2 U5817 ( .A(n3109), .Z(n3076));
+ OR2 U5818 ( .A(po070), .B(n3205), .Z(n3109));
+ IV2 U5819 ( .A(pi128), .Z(n3205));
+ AN2 U5820 ( .A(n5985), .B(n6044), .Z(n6002));
+ OR2 U5821 ( .A(n6045), .B(n6046), .Z(n5927));
+ AN2 U5822 ( .A(n6047), .B(n3945), .Z(n6046));
+ IV2 U5823 ( .A(n4313), .Z(n3945));
+ OR2 U5824 ( .A(n3321), .B(n2837), .Z(n4313));
+ AN2 U5825 ( .A(pi050), .B(n4975), .Z(n6047));
+ AN2 U5826 ( .A(n6048), .B(n6049), .Z(n6045));
+ AN2 U5827 ( .A(n6050), .B(n6051), .Z(n6049));
+ OR2 U5828 ( .A(n3363), .B(n6052), .Z(n6051));
+ OR2 U5829 ( .A(po027), .B(n3989), .Z(n6050));
+ AN2 U5830 ( .A(n6053), .B(n4943), .Z(n6048));
+ OR2 U5831 ( .A(n4239), .B(n4192), .Z(n4312));
+ OR2 U5832 ( .A(n6054), .B(n6055), .Z(po003));
+ OR2 U5833 ( .A(n6056), .B(n6057), .Z(n6055));
+ AN2 U5834 ( .A(n6058), .B(pi054), .Z(n6057));
+ OR2 U5835 ( .A(n6059), .B(n6060), .Z(n6058));
+ AN2 U5836 ( .A(n4177), .B(n5126), .Z(n6060));
+ AN2 U5837 ( .A(n5125), .B(n5898), .Z(n6059));
+ AN2 U5838 ( .A(n6061), .B(n4129), .Z(n6056));
+ AN2 U5839 ( .A(n4177), .B(n5125), .Z(n6061));
+ OR2 U5840 ( .A(n6062), .B(n3257), .Z(n5125));
+ OR2 U5841 ( .A(n5902), .B(n6063), .Z(n3257));
+ OR2 U5842 ( .A(n6064), .B(n6065), .Z(n6063));
+ AN2 U5843 ( .A(n4403), .B(n4319), .Z(n6065));
+ IV2 U5844 ( .A(po004), .Z(n4319));
+ OR2 U5845 ( .A(n6066), .B(n4380), .Z(n4403));
+ AN2 U5846 ( .A(n6067), .B(n3259), .Z(n6066));
+ AN2 U5847 ( .A(n4053), .B(n4013), .Z(n6067));
+ OR2 U5848 ( .A(n6068), .B(n3265), .Z(n4053));
+ AN2 U5849 ( .A(pi058), .B(n3261), .Z(n6068));
+ AN2 U5850 ( .A(n6069), .B(n6070), .Z(n6064));
+ AN2 U5851 ( .A(n4387), .B(n4013), .Z(n6070));
+ IV2 U5852 ( .A(po040), .Z(n4013));
+ AN2 U5853 ( .A(pi065), .B(n3259), .Z(n6069));
+ OR2 U5854 ( .A(n6071), .B(n4379), .Z(n5902));
+ IV2 U5855 ( .A(n4159), .Z(n4379));
+ AN2 U5856 ( .A(n4380), .B(n4404), .Z(n6071));
+ IV2 U5857 ( .A(n4161), .Z(n4404));
+ IV2 U5858 ( .A(n4141), .Z(n4380));
+ OR2 U5859 ( .A(n4016), .B(n6072), .Z(n4141));
+ OR2 U5860 ( .A(n6073), .B(n6074), .Z(n6072));
+ AN2 U5861 ( .A(n6075), .B(n4242), .Z(n6074));
+ OR2 U5862 ( .A(n6076), .B(n6077), .Z(n4016));
+ AN2 U5863 ( .A(n4040), .B(n3951), .Z(n6076));
+ AN2 U5864 ( .A(n3259), .B(n6078), .Z(n6062));
+ OR2 U5865 ( .A(n6079), .B(n3926), .Z(n6078));
+ AN2 U5866 ( .A(n3264), .B(n4387), .Z(n6079));
+ AN2 U5867 ( .A(n3261), .B(n4026), .Z(n4387));
+ IV2 U5868 ( .A(n6080), .Z(n3264));
+ OR2 U5869 ( .A(n6081), .B(n5919), .Z(n6080));
+ AN2 U5870 ( .A(n4330), .B(n6082), .Z(n3259));
+ AN2 U5871 ( .A(n4205), .B(n3314), .Z(n6082));
+ IV2 U5872 ( .A(n5898), .Z(n4177));
+ AN2 U5873 ( .A(n4172), .B(n5126), .Z(n6054));
+ OR2 U5874 ( .A(n6083), .B(n6084), .Z(n5126));
+ OR2 U5875 ( .A(n6085), .B(n6086), .Z(n6084));
+ AN2 U5876 ( .A(n4227), .B(n4159), .Z(n6086));
+ OR2 U5877 ( .A(po004), .B(n4161), .Z(n4159));
+ OR2 U5878 ( .A(n4310), .B(n3321), .Z(n4161));
+ OR2 U5879 ( .A(n6087), .B(n6088), .Z(n4227));
+ OR2 U5880 ( .A(n6089), .B(n6077), .Z(n6088));
+ OR2 U5881 ( .A(n6090), .B(n6091), .Z(n6077));
+ OR2 U5882 ( .A(n3317), .B(n6092), .Z(n6091));
+ AN2 U5883 ( .A(n4291), .B(n4056), .Z(n6092));
+ AN2 U5884 ( .A(n3321), .B(po103), .Z(n3317));
+ AN2 U5885 ( .A(n4040), .B(n3321), .Z(n6090));
+ AN2 U5886 ( .A(n4192), .B(n6075), .Z(n6089));
+ OR2 U5887 ( .A(n3321), .B(n6093), .Z(n6075));
+ OR2 U5888 ( .A(n6073), .B(n6094), .Z(n6087));
+ AN2 U5889 ( .A(n4040), .B(n4291), .Z(n6094));
+ AN2 U5890 ( .A(po040), .B(n6095), .Z(n6073));
+ OR2 U5891 ( .A(n4040), .B(n6096), .Z(n6095));
+ OR2 U5892 ( .A(n3318), .B(n4293), .Z(n6096));
+ OR2 U5893 ( .A(n3951), .B(n3321), .Z(n4293));
+ AN2 U5894 ( .A(n4056), .B(n6097), .Z(n3318));
+ AN2 U5895 ( .A(n4057), .B(pi192), .Z(n6097));
+ IV2 U5896 ( .A(n4026), .Z(n4056));
+ OR2 U5897 ( .A(pi058), .B(n3265), .Z(n4026));
+ IV2 U5898 ( .A(n3314), .Z(n4040));
+ OR2 U5899 ( .A(n6098), .B(n4201), .Z(n3314));
+ IV2 U5900 ( .A(po091), .Z(n4201));
+ AN2 U5901 ( .A(n3261), .B(n4200), .Z(n6098));
+ AN2 U5902 ( .A(n6081), .B(pi192), .Z(n6085));
+ AN2 U5903 ( .A(n4150), .B(po004), .Z(n6081));
+ IV2 U5904 ( .A(pi065), .Z(n4150));
+ OR2 U5905 ( .A(n6099), .B(n4396), .Z(n6083));
+ AN2 U5906 ( .A(n4406), .B(n6100), .Z(n4396));
+ OR2 U5907 ( .A(n6101), .B(n3321), .Z(n6100));
+ AN2 U5908 ( .A(n6102), .B(n6103), .Z(n6101));
+ AN2 U5909 ( .A(n4223), .B(n4057), .Z(n6103));
+ AN2 U5910 ( .A(n4310), .B(n6104), .Z(n6102));
+ OR2 U5911 ( .A(po040), .B(n5919), .Z(n6104));
+ IV2 U5912 ( .A(pi204), .Z(n5919));
+ IV2 U5913 ( .A(n4156), .Z(n4310));
+ OR2 U5914 ( .A(pi065), .B(n2837), .Z(n4156));
+ AN2 U5915 ( .A(po004), .B(n6105), .Z(n6099));
+ OR2 U5916 ( .A(n6106), .B(n3321), .Z(n6105));
+ AN2 U5917 ( .A(n4406), .B(n6093), .Z(n6106));
+ OR2 U5918 ( .A(n6107), .B(n4028), .Z(n6093));
+ AN2 U5919 ( .A(n4223), .B(n4291), .Z(n4028));
+ AN2 U5920 ( .A(n4057), .B(n3951), .Z(n4291));
+ IV2 U5921 ( .A(n4041), .Z(n3951));
+ OR2 U5922 ( .A(pi204), .B(n2837), .Z(n4041));
+ OR2 U5923 ( .A(po103), .B(n4316), .Z(n4223));
+ IV2 U5924 ( .A(pi058), .Z(n4316));
+ AN2 U5925 ( .A(po040), .B(n3322), .Z(n6107));
+ OR2 U5926 ( .A(n4046), .B(n4045), .Z(n3322));
+ OR2 U5927 ( .A(n6108), .B(n6109), .Z(n4045));
+ AN2 U5928 ( .A(n4148), .B(n4057), .Z(n6109));
+ OR2 U5929 ( .A(po091), .B(n3966), .Z(n4057));
+ IV2 U5930 ( .A(pi129), .Z(n3966));
+ AN2 U5931 ( .A(n4203), .B(po103), .Z(n6108));
+ IV2 U5932 ( .A(n4200), .Z(n4203));
+ OR2 U5933 ( .A(pi129), .B(n2837), .Z(n4200));
+ AN2 U5934 ( .A(po103), .B(po091), .Z(n4046));
+ AN2 U5935 ( .A(n5898), .B(n4129), .Z(n4172));
+ IV2 U5936 ( .A(pi054), .Z(n4129));
+ OR2 U5937 ( .A(n4167), .B(n4128), .Z(n5898));
+ IV2 U5938 ( .A(po085), .Z(n4128));
+ IV2 U5939 ( .A(pi052), .Z(n4167));
+ AN2 U5940 ( .A(n6110), .B(n6111), .Z(po002));
+ OR2 U5941 ( .A(n3306), .B(n4450), .Z(n6111));
+ OR2 U5942 ( .A(n4458), .B(n4606), .Z(n6110));
+ IV2 U5943 ( .A(n3306), .Z(n4458));
+ OR2 U5944 ( .A(n6112), .B(n4652), .Z(n3306));
+ OR2 U5945 ( .A(n6113), .B(n6114), .Z(n4652));
+ AN2 U5946 ( .A(n6115), .B(n2837), .Z(n6114));
+ OR2 U5947 ( .A(n6116), .B(n6117), .Z(n6115));
+ AN2 U5948 ( .A(pi108), .B(n4881), .Z(n6117));
+ AN2 U5949 ( .A(n4475), .B(n6118), .Z(n6116));
+ OR2 U5950 ( .A(n5467), .B(n6119), .Z(n6118));
+ IV2 U5951 ( .A(n5488), .Z(n6119));
+ OR2 U5952 ( .A(po102), .B(n5322), .Z(n5488));
+ IV2 U5953 ( .A(pi114), .Z(n5322));
+ AN2 U5954 ( .A(n6120), .B(n6121), .Z(n5467));
+ OR2 U5955 ( .A(pi114), .B(n4885), .Z(n6120));
+ AN2 U5956 ( .A(pi192), .B(n6122), .Z(n6113));
+ OR2 U5957 ( .A(n6123), .B(n6124), .Z(n6122));
+ AN2 U5958 ( .A(pi148), .B(n4881), .Z(n6124));
+ AN2 U5959 ( .A(n4475), .B(n6125), .Z(n6123));
+ OR2 U5960 ( .A(n5466), .B(n6126), .Z(n6125));
+ IV2 U5961 ( .A(n5491), .Z(n6126));
+ OR2 U5962 ( .A(po102), .B(n3901), .Z(n5491));
+ IV2 U5963 ( .A(pi069), .Z(n3901));
+ AN2 U5964 ( .A(n6127), .B(n6128), .Z(n5466));
+ OR2 U5965 ( .A(pi069), .B(n4885), .Z(n6127));
+ AN2 U5966 ( .A(n5461), .B(n4475), .Z(n6112));
+ AN2 U5967 ( .A(n4087), .B(n6129), .Z(n5461));
+ AN2 U5968 ( .A(n6130), .B(n4341), .Z(n6129));
+ IV2 U5969 ( .A(n5474), .Z(n6130));
+ AN2 U5970 ( .A(n6131), .B(po102), .Z(n5474));
+ AN2 U5971 ( .A(n4334), .B(n4333), .Z(n4087));
+ OR2 U5972 ( .A(n6132), .B(n4656), .Z(n4334));
+ OR2 U5973 ( .A(n6133), .B(n6134), .Z(n4656));
+ AN2 U5974 ( .A(n5074), .B(n3083), .Z(n6133));
+ AN2 U5975 ( .A(n6135), .B(n3083), .Z(n6132));
+ AN2 U5976 ( .A(n3018), .B(n4326), .Z(n6135));
+ OR2 U5977 ( .A(n6136), .B(n5077), .Z(n4326));
+ OR2 U5978 ( .A(n6137), .B(n3100), .Z(n5077));
+ AN2 U5979 ( .A(n3280), .B(n4666), .Z(n6137));
+ OR2 U5980 ( .A(n3286), .B(n6138), .Z(n4666));
+ AN2 U5981 ( .A(n5829), .B(n3049), .Z(n3280));
+ AN2 U5982 ( .A(n6139), .B(n3284), .Z(n6136));
+ OR2 U5983 ( .A(n3049), .B(n5829), .Z(n3284));
+ OR2 U5984 ( .A(n6140), .B(n3287), .Z(n6139));
+ OR2 U5985 ( .A(n6141), .B(n6142), .Z(n3287));
+ AN2 U5986 ( .A(pi141), .B(n3173), .Z(n6141));
+ AN2 U5987 ( .A(n6143), .B(n3286), .Z(n6140));
+ OR2 U5988 ( .A(n3173), .B(n3064), .Z(n6143));
+ OR2 U5989 ( .A(n6144), .B(n6145), .Z(po000));
+ AN2 U5990 ( .A(n6146), .B(po103), .Z(n6145));
+ OR2 U5991 ( .A(n6147), .B(n6148), .Z(n6146));
+ AN2 U5992 ( .A(n6149), .B(n3326), .Z(n6148));
+ AN2 U5993 ( .A(n4217), .B(n3320), .Z(n6147));
+ AN2 U5994 ( .A(n6150), .B(n3265), .Z(n6144));
+ IV2 U5995 ( .A(po103), .Z(n3265));
+ OR2 U5996 ( .A(n6151), .B(n6152), .Z(n6150));
+ AN2 U5997 ( .A(n6149), .B(n3320), .Z(n6152));
+ OR2 U5998 ( .A(n4406), .B(n4192), .Z(n3320));
+ IV2 U5999 ( .A(n4205), .Z(n4192));
+ AN2 U6000 ( .A(n4242), .B(n4331), .Z(n4406));
+ IV2 U6001 ( .A(n4330), .Z(n4331));
+ AN2 U6002 ( .A(n4217), .B(n3326), .Z(n6151));
+ OR2 U6003 ( .A(n6153), .B(n4239), .Z(n3326));
+ IV2 U6004 ( .A(n4242), .Z(n4239));
+ OR2 U6005 ( .A(po028), .B(n6154), .Z(n4242));
+ AN2 U6006 ( .A(n6155), .B(n6156), .Z(n6154));
+ OR2 U6007 ( .A(n3321), .B(n3969), .Z(n6156));
+ IV2 U6008 ( .A(pi169), .Z(n3969));
+ AN2 U6009 ( .A(n4330), .B(n4205), .Z(n6153));
+ OR2 U6010 ( .A(n6157), .B(n5056), .Z(n4205));
+ IV2 U6011 ( .A(po028), .Z(n5056));
+ AN2 U6012 ( .A(n3261), .B(n6158), .Z(n6157));
+ OR2 U6013 ( .A(pi169), .B(n2837), .Z(n6158));
+ OR2 U6014 ( .A(n6159), .B(n6160), .Z(n4330));
+ OR2 U6015 ( .A(n6161), .B(n5930), .Z(n6160));
+ OR2 U6016 ( .A(n6162), .B(n6163), .Z(n5930));
+ OR2 U6017 ( .A(n6164), .B(n6165), .Z(n6163));
+ AN2 U6018 ( .A(n3393), .B(n6166), .Z(n6165));
+ OR2 U6019 ( .A(n6167), .B(n5853), .Z(n6166));
+ AN2 U6020 ( .A(n6168), .B(n3371), .Z(n6167));
+ IV2 U6021 ( .A(n3412), .Z(n3371));
+ AN2 U6022 ( .A(n5999), .B(n6053), .Z(n6164));
+ AN2 U6023 ( .A(n3453), .B(n3363), .Z(n5999));
+ AN2 U6024 ( .A(n3926), .B(n4975), .Z(n6162));
+ AN2 U6025 ( .A(n3940), .B(n4975), .Z(n6161));
+ OR2 U6026 ( .A(n6169), .B(n6170), .Z(n6159));
+ AN2 U6027 ( .A(n5931), .B(n6171), .Z(n6170));
+ OR2 U6028 ( .A(n6172), .B(n6173), .Z(n6171));
+ OR2 U6029 ( .A(n6174), .B(n6175), .Z(n6173));
+ AN2 U6030 ( .A(n5888), .B(n3363), .Z(n6175));
+ OR2 U6031 ( .A(n6176), .B(n6177), .Z(n5888));
+ OR2 U6032 ( .A(n3248), .B(n6178), .Z(n6177));
+ AN2 U6033 ( .A(n5833), .B(n3250), .Z(n6178));
+ AN2 U6034 ( .A(n4937), .B(n6179), .Z(n5833));
+ OR2 U6035 ( .A(n6180), .B(n6181), .Z(n6176));
+ AN2 U6036 ( .A(n3495), .B(n5835), .Z(n6181));
+ OR2 U6037 ( .A(n6182), .B(n5894), .Z(n5835));
+ AN2 U6038 ( .A(n5966), .B(n6183), .Z(n6182));
+ OR2 U6039 ( .A(n6184), .B(n6185), .Z(n5966));
+ AN2 U6040 ( .A(pi171), .B(pi192), .Z(n6185));
+ AN2 U6041 ( .A(pi142), .B(n2837), .Z(n6184));
+ AN2 U6042 ( .A(n6186), .B(n5836), .Z(n6180));
+ OR2 U6043 ( .A(n6187), .B(n6188), .Z(n5836));
+ AN2 U6044 ( .A(n3705), .B(n5843), .Z(n6188));
+ AN2 U6045 ( .A(pi192), .B(pi098), .Z(n3705));
+ AN2 U6046 ( .A(n3717), .B(n6189), .Z(n6187));
+ AN2 U6047 ( .A(n2837), .B(pi003), .Z(n3717));
+ AN2 U6048 ( .A(n5889), .B(n3534), .Z(n6174));
+ AN2 U6049 ( .A(n3261), .B(pi060), .Z(n3534));
+ AN2 U6050 ( .A(pi192), .B(n6190), .Z(n5889));
+ OR2 U6051 ( .A(n6191), .B(n6192), .Z(n6190));
+ OR2 U6052 ( .A(n6193), .B(n6194), .Z(n6192));
+ AN2 U6053 ( .A(pi004), .B(n4947), .Z(n6194));
+ AN2 U6054 ( .A(n3640), .B(n3250), .Z(n6193));
+ IV2 U6055 ( .A(n3344), .Z(n3250));
+ IV2 U6056 ( .A(n3632), .Z(n3640));
+ OR2 U6057 ( .A(po001), .B(n3998), .Z(n3632));
+ OR2 U6058 ( .A(n6195), .B(n6196), .Z(n6191));
+ AN2 U6059 ( .A(n6197), .B(n3495), .Z(n6196));
+ AN2 U6060 ( .A(pi171), .B(n6183), .Z(n6197));
+ AN2 U6061 ( .A(n6198), .B(n6186), .Z(n6195));
+ IV2 U6062 ( .A(n6199), .Z(n6186));
+ AN2 U6063 ( .A(pi098), .B(n5843), .Z(n6198));
+ OR2 U6064 ( .A(pi171), .B(n4441), .Z(n5843));
+ OR2 U6065 ( .A(n5892), .B(n6200), .Z(n6172));
+ AN2 U6066 ( .A(n6201), .B(n5894), .Z(n6200));
+ AN2 U6067 ( .A(n4441), .B(n4417), .Z(n5894));
+ AN2 U6068 ( .A(n3495), .B(n3453), .Z(n6201));
+ IV2 U6069 ( .A(n3451), .Z(n3453));
+ OR2 U6070 ( .A(n3533), .B(n3321), .Z(n3451));
+ IV2 U6071 ( .A(n3477), .Z(n3533));
+ OR2 U6072 ( .A(pi060), .B(n2837), .Z(n3477));
+ IV2 U6073 ( .A(n6202), .Z(n3495));
+ IV2 U6074 ( .A(n6203), .Z(n5892));
+ OR2 U6075 ( .A(n6204), .B(n6155), .Z(n6203));
+ AN2 U6076 ( .A(n6205), .B(n6206), .Z(n6204));
+ AN2 U6077 ( .A(n6207), .B(n6208), .Z(n6206));
+ OR2 U6078 ( .A(n6199), .B(n6209), .Z(n6208));
+ OR2 U6079 ( .A(n3244), .B(n3597), .Z(n6209));
+ IV2 U6080 ( .A(pi003), .Z(n3597));
+ IV2 U6081 ( .A(n6189), .Z(n3244));
+ OR2 U6082 ( .A(pi142), .B(n4441), .Z(n6189));
+ OR2 U6083 ( .A(n4418), .B(n6202), .Z(n6199));
+ IV2 U6084 ( .A(n4426), .Z(n4418));
+ OR2 U6085 ( .A(n3688), .B(n3290), .Z(n4426));
+ IV2 U6086 ( .A(po011), .Z(n3688));
+ OR2 U6087 ( .A(n6202), .B(n6210), .Z(n6207));
+ OR2 U6088 ( .A(n4430), .B(n4440), .Z(n6210));
+ IV2 U6089 ( .A(pi142), .Z(n4440));
+ IV2 U6090 ( .A(n6183), .Z(n4430));
+ OR2 U6091 ( .A(n4417), .B(n4441), .Z(n6183));
+ IV2 U6092 ( .A(po036), .Z(n4441));
+ IV2 U6093 ( .A(n3236), .Z(n4417));
+ OR2 U6094 ( .A(n3234), .B(po011), .Z(n3236));
+ IV2 U6095 ( .A(n3290), .Z(n3234));
+ OR2 U6096 ( .A(n6211), .B(n6212), .Z(n3290));
+ OR2 U6097 ( .A(n6213), .B(n6214), .Z(n6212));
+ OR2 U6098 ( .A(n6215), .B(n6216), .Z(n6214));
+ AN2 U6099 ( .A(pi192), .B(n5980), .Z(n6216));
+ OR2 U6100 ( .A(n6217), .B(n6218), .Z(n5980));
+ OR2 U6101 ( .A(n6219), .B(n6220), .Z(n6218));
+ AN2 U6102 ( .A(pi045), .B(n4915), .Z(n6220));
+ AN2 U6103 ( .A(n4621), .B(n4751), .Z(n6219));
+ IV2 U6104 ( .A(n4465), .Z(n4621));
+ OR2 U6105 ( .A(po014), .B(n3908), .Z(n4465));
+ IV2 U6106 ( .A(pi079), .Z(n3908));
+ OR2 U6107 ( .A(n6221), .B(n6222), .Z(n6217));
+ AN2 U6108 ( .A(n6223), .B(n3757), .Z(n6222));
+ AN2 U6109 ( .A(pi158), .B(n4628), .Z(n6223));
+ AN2 U6110 ( .A(n6224), .B(n6225), .Z(n6221));
+ AN2 U6111 ( .A(pi175), .B(n5037), .Z(n6224));
+ AN2 U6112 ( .A(n6008), .B(n2837), .Z(n6215));
+ OR2 U6113 ( .A(n6226), .B(n6227), .Z(n6008));
+ OR2 U6114 ( .A(n6228), .B(n6229), .Z(n6227));
+ AN2 U6115 ( .A(pi095), .B(n4915), .Z(n6229));
+ AN2 U6116 ( .A(n4623), .B(n4751), .Z(n6228));
+ IV2 U6117 ( .A(n4469), .Z(n4623));
+ OR2 U6118 ( .A(po014), .B(n4648), .Z(n4469));
+ IV2 U6119 ( .A(pi156), .Z(n4648));
+ OR2 U6120 ( .A(n6230), .B(n6231), .Z(n6226));
+ AN2 U6121 ( .A(n6232), .B(n3757), .Z(n6231));
+ AN2 U6122 ( .A(pi151), .B(n4628), .Z(n6232));
+ AN2 U6123 ( .A(n6233), .B(n6225), .Z(n6230));
+ AN2 U6124 ( .A(pi185), .B(n5037), .Z(n6233));
+ AN2 U6125 ( .A(n5985), .B(n6234), .Z(n6213));
+ OR2 U6126 ( .A(n6235), .B(n6236), .Z(n6234));
+ OR2 U6127 ( .A(n6237), .B(n6238), .Z(n6236));
+ OR2 U6128 ( .A(n6239), .B(n6240), .Z(n6238));
+ AN2 U6129 ( .A(n6241), .B(n3055), .Z(n6240));
+ AN2 U6130 ( .A(n5822), .B(n3119), .Z(n6241));
+ OR2 U6131 ( .A(n6242), .B(n6016), .Z(n3119));
+ AN2 U6132 ( .A(pi141), .B(po099), .Z(n6242));
+ AN2 U6133 ( .A(n5994), .B(n6243), .Z(n6239));
+ AN2 U6134 ( .A(n6244), .B(n3049), .Z(n6237));
+ OR2 U6135 ( .A(n6243), .B(n6245), .Z(n6244));
+ OR2 U6136 ( .A(n6020), .B(n6246), .Z(n6245));
+ AN2 U6137 ( .A(n6247), .B(n5826), .Z(n6246));
+ AN2 U6138 ( .A(n3106), .B(n5829), .Z(n5826));
+ OR2 U6139 ( .A(n5994), .B(n5822), .Z(n5829));
+ IV2 U6140 ( .A(pi166), .Z(n3106));
+ AN2 U6141 ( .A(n3063), .B(pi192), .Z(n6247));
+ AN2 U6142 ( .A(n6016), .B(n5994), .Z(n6020));
+ AN2 U6143 ( .A(n3286), .B(n3177), .Z(n6016));
+ OR2 U6144 ( .A(n6142), .B(n6248), .Z(n6243));
+ AN2 U6145 ( .A(n3207), .B(n3286), .Z(n6248));
+ OR2 U6146 ( .A(n6249), .B(n6250), .Z(n3207));
+ AN2 U6147 ( .A(n3064), .B(n3171), .Z(n6250));
+ AN2 U6148 ( .A(n3173), .B(n3177), .Z(n6249));
+ IV2 U6149 ( .A(pi141), .Z(n3177));
+ AN2 U6150 ( .A(pi033), .B(n3064), .Z(n6142));
+ OR2 U6151 ( .A(n6251), .B(n6252), .Z(n6235));
+ OR2 U6152 ( .A(n6044), .B(n3100), .Z(n6252));
+ AN2 U6153 ( .A(n3286), .B(n6138), .Z(n3100));
+ OR2 U6154 ( .A(n6253), .B(n6254), .Z(n6138));
+ AN2 U6155 ( .A(pi033), .B(pi192), .Z(n6254));
+ AN2 U6156 ( .A(pi141), .B(n2837), .Z(n6253));
+ AN2 U6157 ( .A(n6255), .B(pi141), .Z(n6044));
+ OR2 U6158 ( .A(n3071), .B(n6256), .Z(n6255));
+ AN2 U6159 ( .A(n3055), .B(n5994), .Z(n6256));
+ IV2 U6160 ( .A(n6257), .Z(n5994));
+ OR2 U6161 ( .A(n2925), .B(n5099), .Z(n6257));
+ OR2 U6162 ( .A(n6258), .B(n6259), .Z(n5099));
+ OR2 U6163 ( .A(n3146), .B(n6260), .Z(n6259));
+ OR2 U6164 ( .A(n6261), .B(n6262), .Z(n6260));
+ AN2 U6165 ( .A(n2845), .B(n2837), .Z(n6262));
+ IV2 U6166 ( .A(n2846), .Z(n2845));
+ AN2 U6167 ( .A(n6263), .B(n6264), .Z(n2846));
+ OR2 U6168 ( .A(n3141), .B(po044), .Z(n6263));
+ IV2 U6169 ( .A(pi201), .Z(n3141));
+ AN2 U6170 ( .A(pi192), .B(n2833), .Z(n6261));
+ IV2 U6171 ( .A(n2834), .Z(n2833));
+ AN2 U6172 ( .A(n6265), .B(n6266), .Z(n2834));
+ OR2 U6173 ( .A(n3136), .B(po044), .Z(n6265));
+ IV2 U6174 ( .A(pi088), .Z(n3136));
+ OR2 U6175 ( .A(n6267), .B(n6268), .Z(n3146));
+ AN2 U6176 ( .A(n2880), .B(pi192), .Z(n6268));
+ IV2 U6177 ( .A(n2878), .Z(n2880));
+ OR2 U6178 ( .A(pi077), .B(n2962), .Z(n2878));
+ AN2 U6179 ( .A(n2978), .B(n2837), .Z(n6267));
+ IV2 U6180 ( .A(n2939), .Z(n2978));
+ OR2 U6181 ( .A(n2998), .B(n6269), .Z(n6258));
+ OR2 U6182 ( .A(n2901), .B(n2862), .Z(n6269));
+ IV2 U6183 ( .A(pi200), .Z(n2901));
+ IV2 U6184 ( .A(n3003), .Z(n2925));
+ OR2 U6185 ( .A(pi192), .B(n2960), .Z(n3003));
+ IV2 U6186 ( .A(n6270), .Z(n2960));
+ OR2 U6187 ( .A(n6271), .B(n6272), .Z(n6270));
+ AN2 U6188 ( .A(pi081), .B(n2931), .Z(n6272));
+ IV2 U6189 ( .A(po107), .Z(n2931));
+ AN2 U6190 ( .A(po107), .B(n2982), .Z(n6271));
+ AN2 U6191 ( .A(n2837), .B(n6017), .Z(n3055));
+ IV2 U6192 ( .A(n5828), .Z(n6017));
+ OR2 U6193 ( .A(n6273), .B(n6015), .Z(n5828));
+ AN2 U6194 ( .A(pi174), .B(n3049), .Z(n6015));
+ AN2 U6195 ( .A(po010), .B(n5115), .Z(n6273));
+ IV2 U6196 ( .A(pi174), .Z(n5115));
+ AN2 U6197 ( .A(n3049), .B(n3173), .Z(n3071));
+ AN2 U6198 ( .A(n2837), .B(pi174), .Z(n3173));
+ IV2 U6199 ( .A(po010), .Z(n3049));
+ AN2 U6200 ( .A(n6274), .B(n3063), .Z(n6251));
+ IV2 U6201 ( .A(n6275), .Z(n3063));
+ OR2 U6202 ( .A(n6276), .B(n6277), .Z(n6275));
+ AN2 U6203 ( .A(pi033), .B(n3286), .Z(n6277));
+ IV2 U6204 ( .A(po099), .Z(n3286));
+ AN2 U6205 ( .A(po099), .B(n3171), .Z(n6276));
+ IV2 U6206 ( .A(pi033), .Z(n3171));
+ AN2 U6207 ( .A(n3064), .B(n5822), .Z(n6274));
+ OR2 U6208 ( .A(n6278), .B(n6279), .Z(n5822));
+ OR2 U6209 ( .A(n6280), .B(n6281), .Z(n6279));
+ AN2 U6210 ( .A(n6282), .B(pi192), .Z(n6281));
+ AN2 U6211 ( .A(n5156), .B(n6266), .Z(n6282));
+ OR2 U6212 ( .A(pi088), .B(n5000), .Z(n6266));
+ OR2 U6213 ( .A(n6283), .B(n5153), .Z(n5156));
+ AN2 U6214 ( .A(n2861), .B(n6284), .Z(n6283));
+ OR2 U6215 ( .A(n2885), .B(n2892), .Z(n6284));
+ AN2 U6216 ( .A(n5008), .B(pi157), .Z(n2892));
+ AN2 U6217 ( .A(n2930), .B(n2876), .Z(n2885));
+ IV2 U6218 ( .A(n2887), .Z(n2876));
+ OR2 U6219 ( .A(po031), .B(n3846), .Z(n2887));
+ IV2 U6220 ( .A(pi077), .Z(n3846));
+ AN2 U6221 ( .A(n6285), .B(n2837), .Z(n6280));
+ AN2 U6222 ( .A(n5175), .B(n6264), .Z(n6285));
+ OR2 U6223 ( .A(pi201), .B(n5000), .Z(n6264));
+ OR2 U6224 ( .A(n6286), .B(n6287), .Z(n5175));
+ AN2 U6225 ( .A(n2861), .B(n6288), .Z(n6286));
+ OR2 U6226 ( .A(n6289), .B(n2929), .Z(n6288));
+ IV2 U6227 ( .A(n2947), .Z(n2929));
+ OR2 U6228 ( .A(po106), .B(n5431), .Z(n2947));
+ IV2 U6229 ( .A(pi206), .Z(n5431));
+ AN2 U6230 ( .A(n2930), .B(n4113), .Z(n6289));
+ OR2 U6231 ( .A(n2919), .B(n2936), .Z(n4113));
+ IV2 U6232 ( .A(n2946), .Z(n2936));
+ OR2 U6233 ( .A(po031), .B(n2957), .Z(n2946));
+ IV2 U6234 ( .A(pi082), .Z(n2957));
+ AN2 U6235 ( .A(n2902), .B(n2939), .Z(n2919));
+ OR2 U6236 ( .A(pi082), .B(n2962), .Z(n2939));
+ IV2 U6237 ( .A(po031), .Z(n2962));
+ IV2 U6238 ( .A(n2974), .Z(n2902));
+ OR2 U6239 ( .A(po107), .B(n2982), .Z(n2974));
+ IV2 U6240 ( .A(pi081), .Z(n2982));
+ IV2 U6241 ( .A(n2862), .Z(n2930));
+ OR2 U6242 ( .A(n6290), .B(n6291), .Z(n2862));
+ AN2 U6243 ( .A(n6292), .B(n5008), .Z(n6291));
+ IV2 U6244 ( .A(po106), .Z(n5008));
+ AN2 U6245 ( .A(n6293), .B(po106), .Z(n6290));
+ IV2 U6246 ( .A(n6292), .Z(n6293));
+ OR2 U6247 ( .A(n6294), .B(n6295), .Z(n6292));
+ AN2 U6248 ( .A(pi192), .B(pi157), .Z(n6295));
+ AN2 U6249 ( .A(pi206), .B(n2837), .Z(n6294));
+ IV2 U6250 ( .A(n2998), .Z(n2861));
+ OR2 U6251 ( .A(n6296), .B(n6297), .Z(n2998));
+ OR2 U6252 ( .A(n6298), .B(n6299), .Z(n6297));
+ AN2 U6253 ( .A(n5153), .B(pi192), .Z(n6299));
+ AN2 U6254 ( .A(n5004), .B(pi026), .Z(n5153));
+ IV2 U6255 ( .A(po079), .Z(n5004));
+ AN2 U6256 ( .A(n6287), .B(n2837), .Z(n6298));
+ IV2 U6257 ( .A(n5172), .Z(n6287));
+ OR2 U6258 ( .A(po079), .B(n5165), .Z(n5172));
+ AN2 U6259 ( .A(po079), .B(n6027), .Z(n6296));
+ OR2 U6260 ( .A(n6300), .B(n6301), .Z(n6027));
+ AN2 U6261 ( .A(pi192), .B(n3847), .Z(n6301));
+ IV2 U6262 ( .A(pi026), .Z(n3847));
+ AN2 U6263 ( .A(n5165), .B(n2837), .Z(n6300));
+ IV2 U6264 ( .A(pi107), .Z(n5165));
+ AN2 U6265 ( .A(n3011), .B(n5000), .Z(n6278));
+ IV2 U6266 ( .A(po044), .Z(n5000));
+ OR2 U6267 ( .A(n6302), .B(n6303), .Z(n3011));
+ AN2 U6268 ( .A(pi088), .B(pi192), .Z(n6303));
+ AN2 U6269 ( .A(pi201), .B(n2837), .Z(n6302));
+ AN2 U6270 ( .A(pi192), .B(pi166), .Z(n3064));
+ AN2 U6271 ( .A(n3018), .B(n5984), .Z(n5985));
+ AN2 U6272 ( .A(n6304), .B(n5104), .Z(n3018));
+ IV2 U6273 ( .A(n5074), .Z(n5104));
+ OR2 U6274 ( .A(n6305), .B(n5040), .Z(n6304));
+ OR2 U6275 ( .A(n6306), .B(n6307), .Z(n6211));
+ OR2 U6276 ( .A(n6308), .B(n6309), .Z(n6307));
+ AN2 U6277 ( .A(n4624), .B(n5981), .Z(n6309));
+ AN2 U6278 ( .A(n3300), .B(n3305), .Z(n4624));
+ AN2 U6279 ( .A(n5984), .B(n5074), .Z(n6308));
+ AN2 U6280 ( .A(n5040), .B(n6305), .Z(n5074));
+ OR2 U6281 ( .A(n6310), .B(n6311), .Z(n6305));
+ AN2 U6282 ( .A(pi096), .B(pi192), .Z(n6311));
+ AN2 U6283 ( .A(pi128), .B(n2837), .Z(n6310));
+ IV2 U6284 ( .A(po070), .Z(n5040));
+ AN2 U6285 ( .A(n3083), .B(n6225), .Z(n5984));
+ AN2 U6286 ( .A(n6312), .B(n6313), .Z(n6225));
+ AN2 U6287 ( .A(n3760), .B(n4341), .Z(n6313));
+ AN2 U6288 ( .A(n4333), .B(n4482), .Z(n6312));
+ OR2 U6289 ( .A(n6314), .B(n6315), .Z(n4333));
+ AN2 U6290 ( .A(po025), .B(n6316), .Z(n6315));
+ OR2 U6291 ( .A(n6317), .B(n3888), .Z(n6316));
+ AN2 U6292 ( .A(pi192), .B(pi191), .Z(n3888));
+ AN2 U6293 ( .A(pi076), .B(n2837), .Z(n6317));
+ AN2 U6294 ( .A(n3781), .B(n4557), .Z(n6314));
+ OR2 U6295 ( .A(n4538), .B(n3890), .Z(n3781));
+ IV2 U6296 ( .A(n6318), .Z(n3890));
+ OR2 U6297 ( .A(pi191), .B(n2837), .Z(n6318));
+ AN2 U6298 ( .A(n4077), .B(n2837), .Z(n4538));
+ IV2 U6299 ( .A(n3021), .Z(n3083));
+ OR2 U6300 ( .A(n6319), .B(n6134), .Z(n3021));
+ AN2 U6301 ( .A(n6320), .B(n5037), .Z(n6134));
+ IV2 U6302 ( .A(po035), .Z(n5037));
+ AN2 U6303 ( .A(n6321), .B(po035), .Z(n6319));
+ IV2 U6304 ( .A(n6320), .Z(n6321));
+ OR2 U6305 ( .A(n6322), .B(n6323), .Z(n6320));
+ AN2 U6306 ( .A(pi175), .B(pi192), .Z(n6323));
+ AN2 U6307 ( .A(pi185), .B(n2837), .Z(n6322));
+ AN2 U6308 ( .A(n3760), .B(n6324), .Z(n6306));
+ OR2 U6309 ( .A(n6325), .B(n6326), .Z(n6324));
+ OR2 U6310 ( .A(n6327), .B(n6328), .Z(n6326));
+ AN2 U6311 ( .A(n4482), .B(n4340), .Z(n6328));
+ OR2 U6312 ( .A(n6329), .B(n6330), .Z(n4340));
+ AN2 U6313 ( .A(n6121), .B(n2837), .Z(n6330));
+ OR2 U6314 ( .A(n6331), .B(n4567), .Z(n6121));
+ IV2 U6315 ( .A(n4578), .Z(n4567));
+ OR2 U6316 ( .A(po024), .B(n4358), .Z(n4578));
+ AN2 U6317 ( .A(n4084), .B(n4066), .Z(n6331));
+ OR2 U6318 ( .A(n6332), .B(n4539), .Z(n4084));
+ IV2 U6319 ( .A(n5503), .Z(n4539));
+ OR2 U6320 ( .A(po059), .B(n4074), .Z(n5503));
+ IV2 U6321 ( .A(pi170), .Z(n4074));
+ AN2 U6322 ( .A(n4576), .B(n3778), .Z(n6332));
+ IV2 U6323 ( .A(n4580), .Z(n4576));
+ OR2 U6324 ( .A(po025), .B(n4077), .Z(n4580));
+ IV2 U6325 ( .A(pi076), .Z(n4077));
+ AN2 U6326 ( .A(pi192), .B(n6128), .Z(n6329));
+ OR2 U6327 ( .A(n6333), .B(n6334), .Z(n6128));
+ OR2 U6328 ( .A(n4561), .B(n6335), .Z(n6334));
+ AN2 U6329 ( .A(n6336), .B(n4341), .Z(n6335));
+ AN2 U6330 ( .A(n4066), .B(n3778), .Z(n4341));
+ IV2 U6331 ( .A(n3773), .Z(n3778));
+ OR2 U6332 ( .A(n6337), .B(n6338), .Z(n3773));
+ AN2 U6333 ( .A(n6339), .B(n4877), .Z(n6338));
+ IV2 U6334 ( .A(po059), .Z(n4877));
+ AN2 U6335 ( .A(n6340), .B(po059), .Z(n6337));
+ IV2 U6336 ( .A(n6339), .Z(n6340));
+ OR2 U6337 ( .A(n6341), .B(n6342), .Z(n6339));
+ AN2 U6338 ( .A(pi135), .B(pi192), .Z(n6342));
+ AN2 U6339 ( .A(pi170), .B(n2837), .Z(n6341));
+ AN2 U6340 ( .A(pi191), .B(n4557), .Z(n6336));
+ IV2 U6341 ( .A(po025), .Z(n4557));
+ IV2 U6342 ( .A(n4348), .Z(n4561));
+ OR2 U6343 ( .A(po024), .B(n3896), .Z(n4348));
+ AN2 U6344 ( .A(n4085), .B(n4066), .Z(n6333));
+ OR2 U6345 ( .A(n6343), .B(n6344), .Z(n4066));
+ OR2 U6346 ( .A(n6345), .B(n6346), .Z(n6344));
+ AN2 U6347 ( .A(n6347), .B(po024), .Z(n6346));
+ AN2 U6348 ( .A(pi005), .B(pi192), .Z(n6347));
+ AN2 U6349 ( .A(n6348), .B(n4874), .Z(n6345));
+ IV2 U6350 ( .A(po024), .Z(n4874));
+ OR2 U6351 ( .A(n6349), .B(n5483), .Z(n6348));
+ AN2 U6352 ( .A(pi192), .B(n3896), .Z(n5483));
+ IV2 U6353 ( .A(pi005), .Z(n3896));
+ AN2 U6354 ( .A(n4358), .B(n2837), .Z(n6349));
+ IV2 U6355 ( .A(pi160), .Z(n4358));
+ AN2 U6356 ( .A(pi160), .B(n5477), .Z(n6343));
+ AN2 U6357 ( .A(n2837), .B(po024), .Z(n5477));
+ IV2 U6358 ( .A(n4353), .Z(n4085));
+ OR2 U6359 ( .A(po059), .B(n3880), .Z(n4353));
+ IV2 U6360 ( .A(pi135), .Z(n3880));
+ AN2 U6361 ( .A(n4342), .B(n4475), .Z(n4482));
+ AN2 U6362 ( .A(n6350), .B(n6351), .Z(n4342));
+ OR2 U6363 ( .A(n6131), .B(po102), .Z(n6351));
+ IV2 U6364 ( .A(n6352), .Z(n6131));
+ OR2 U6365 ( .A(n6352), .B(n4885), .Z(n6350));
+ AN2 U6366 ( .A(n5462), .B(n4475), .Z(n6327));
+ IV2 U6367 ( .A(n4478), .Z(n4475));
+ OR2 U6368 ( .A(n6353), .B(n6325), .Z(n4478));
+ AN2 U6369 ( .A(n6354), .B(po072), .Z(n6353));
+ IV2 U6370 ( .A(n6355), .Z(n6354));
+ AN2 U6371 ( .A(n6352), .B(n4885), .Z(n5462));
+ IV2 U6372 ( .A(po102), .Z(n4885));
+ OR2 U6373 ( .A(n6356), .B(n6357), .Z(n6352));
+ AN2 U6374 ( .A(pi069), .B(pi192), .Z(n6357));
+ AN2 U6375 ( .A(pi114), .B(n2837), .Z(n6356));
+ AN2 U6376 ( .A(n6355), .B(n4881), .Z(n6325));
+ IV2 U6377 ( .A(po072), .Z(n4881));
+ OR2 U6378 ( .A(n6358), .B(n6359), .Z(n6355));
+ AN2 U6379 ( .A(pi148), .B(pi192), .Z(n6359));
+ AN2 U6380 ( .A(pi108), .B(n2837), .Z(n6358));
+ AN2 U6381 ( .A(n4450), .B(n5981), .Z(n3760));
+ AN2 U6382 ( .A(n3301), .B(n4751), .Z(n5981));
+ AN2 U6383 ( .A(n4006), .B(n3757), .Z(n4751));
+ IV2 U6384 ( .A(n4444), .Z(n3757));
+ OR2 U6385 ( .A(n6360), .B(n3754), .Z(n4444));
+ AN2 U6386 ( .A(n6361), .B(n4915), .Z(n3754));
+ IV2 U6387 ( .A(po063), .Z(n4915));
+ AN2 U6388 ( .A(n6362), .B(po063), .Z(n6360));
+ IV2 U6389 ( .A(n6361), .Z(n6362));
+ OR2 U6390 ( .A(n6363), .B(n6364), .Z(n6361));
+ AN2 U6391 ( .A(pi045), .B(pi192), .Z(n6364));
+ AN2 U6392 ( .A(pi095), .B(n2837), .Z(n6363));
+ AN2 U6393 ( .A(n6365), .B(n6366), .Z(n4006));
+ OR2 U6394 ( .A(n6367), .B(po092), .Z(n6366));
+ IV2 U6395 ( .A(n4752), .Z(n6367));
+ OR2 U6396 ( .A(n4752), .B(n4628), .Z(n6365));
+ IV2 U6397 ( .A(po092), .Z(n4628));
+ OR2 U6398 ( .A(n6368), .B(n6369), .Z(n4752));
+ AN2 U6399 ( .A(pi158), .B(pi192), .Z(n6369));
+ AN2 U6400 ( .A(pi151), .B(n2837), .Z(n6368));
+ IV2 U6401 ( .A(n3295), .Z(n3301));
+ OR2 U6402 ( .A(n6370), .B(n6371), .Z(n3295));
+ AN2 U6403 ( .A(n4703), .B(n4861), .Z(n6371));
+ IV2 U6404 ( .A(po014), .Z(n4861));
+ AN2 U6405 ( .A(n4736), .B(po014), .Z(n6370));
+ IV2 U6406 ( .A(n4703), .Z(n4736));
+ OR2 U6407 ( .A(n6372), .B(n6373), .Z(n4703));
+ AN2 U6408 ( .A(pi079), .B(pi192), .Z(n6373));
+ AN2 U6409 ( .A(pi156), .B(n2837), .Z(n6372));
+ IV2 U6410 ( .A(n4606), .Z(n4450));
+ AN2 U6411 ( .A(n6374), .B(n6375), .Z(n4606));
+ OR2 U6412 ( .A(n3305), .B(po039), .Z(n6375));
+ OR2 U6413 ( .A(n3300), .B(n6376), .Z(n6374));
+ IV2 U6414 ( .A(n3305), .Z(n6376));
+ OR2 U6415 ( .A(n4685), .B(n4692), .Z(n3305));
+ AN2 U6416 ( .A(pi192), .B(pi016), .Z(n4692));
+ AN2 U6417 ( .A(n2837), .B(pi040), .Z(n4685));
+ IV2 U6418 ( .A(po039), .Z(n3300));
+ OR2 U6419 ( .A(n3352), .B(n3344), .Z(n6202));
+ AN2 U6420 ( .A(n6377), .B(n6378), .Z(n3352));
+ OR2 U6421 ( .A(n6179), .B(po001), .Z(n6378));
+ IV2 U6422 ( .A(n6379), .Z(n6179));
+ OR2 U6423 ( .A(n6379), .B(n4937), .Z(n6377));
+ IV2 U6424 ( .A(po001), .Z(n4937));
+ OR2 U6425 ( .A(n5959), .B(n6380), .Z(n6379));
+ AN2 U6426 ( .A(pi192), .B(n3998), .Z(n6380));
+ IV2 U6427 ( .A(pi068), .Z(n3998));
+ AN2 U6428 ( .A(n2837), .B(n5379), .Z(n5959));
+ AN2 U6429 ( .A(n6381), .B(n6382), .Z(n6205));
+ OR2 U6430 ( .A(n3344), .B(n3590), .Z(n6382));
+ OR2 U6431 ( .A(po001), .B(n5379), .Z(n3590));
+ IV2 U6432 ( .A(pi195), .Z(n5379));
+ OR2 U6433 ( .A(n6383), .B(n3248), .Z(n3344));
+ AN2 U6434 ( .A(n6384), .B(n4947), .Z(n3248));
+ IV2 U6435 ( .A(po082), .Z(n4947));
+ AN2 U6436 ( .A(n6385), .B(po082), .Z(n6383));
+ IV2 U6437 ( .A(n6384), .Z(n6385));
+ OR2 U6438 ( .A(n6386), .B(n6387), .Z(n6384));
+ AN2 U6439 ( .A(pi004), .B(pi192), .Z(n6387));
+ AN2 U6440 ( .A(pi130), .B(n2837), .Z(n6386));
+ OR2 U6441 ( .A(po082), .B(n5372), .Z(n6381));
+ IV2 U6442 ( .A(pi130), .Z(n5372));
+ AN2 U6443 ( .A(n3225), .B(n6053), .Z(n5931));
+ IV2 U6444 ( .A(n3247), .Z(n3225));
+ OR2 U6445 ( .A(n6388), .B(n3490), .Z(n3247));
+ AN2 U6446 ( .A(n4943), .B(n5895), .Z(n3490));
+ OR2 U6447 ( .A(n3926), .B(n3989), .Z(n5895));
+ IV2 U6448 ( .A(n6389), .Z(n6388));
+ OR2 U6449 ( .A(n4943), .B(n6390), .Z(n6389));
+ AN2 U6450 ( .A(n6391), .B(n3261), .Z(n6390));
+ OR2 U6451 ( .A(n2837), .B(pi133), .Z(n6391));
+ AN2 U6452 ( .A(n6392), .B(n6053), .Z(n6169));
+ AN2 U6453 ( .A(n3393), .B(n6393), .Z(n6053));
+ IV2 U6454 ( .A(n3461), .Z(n6393));
+ OR2 U6455 ( .A(n3401), .B(n3412), .Z(n3461));
+ OR2 U6456 ( .A(n6394), .B(n5853), .Z(n3412));
+ OR2 U6457 ( .A(n3466), .B(n3392), .Z(n5853));
+ AN2 U6458 ( .A(n3380), .B(n3926), .Z(n3392));
+ IV2 U6459 ( .A(po071), .Z(n3380));
+ AN2 U6460 ( .A(n3261), .B(n3381), .Z(n3466));
+ IV2 U6461 ( .A(n3399), .Z(n3381));
+ OR2 U6462 ( .A(po071), .B(n3913), .Z(n3399));
+ AN2 U6463 ( .A(po071), .B(n5878), .Z(n6394));
+ OR2 U6464 ( .A(n3480), .B(n3321), .Z(n5878));
+ AN2 U6465 ( .A(n3913), .B(pi192), .Z(n3480));
+ IV2 U6466 ( .A(pi118), .Z(n3913));
+ OR2 U6467 ( .A(n5881), .B(n6395), .Z(n3401));
+ OR2 U6468 ( .A(n6168), .B(n6396), .Z(n6395));
+ AN2 U6469 ( .A(po104), .B(n3321), .Z(n6396));
+ AN2 U6470 ( .A(n3485), .B(n3261), .Z(n6168));
+ IV2 U6471 ( .A(n3419), .Z(n3485));
+ OR2 U6472 ( .A(n6397), .B(po104), .Z(n3419));
+ AN2 U6473 ( .A(pi192), .B(n3942), .Z(n6397));
+ IV2 U6474 ( .A(pi196), .Z(n3942));
+ AN2 U6475 ( .A(pi192), .B(n5872), .Z(n5881));
+ IV2 U6476 ( .A(n5866), .Z(n5872));
+ OR2 U6477 ( .A(pi196), .B(n3512), .Z(n5866));
+ IV2 U6478 ( .A(po104), .Z(n3512));
+ OR2 U6479 ( .A(n6398), .B(n6399), .Z(n3393));
+ AN2 U6480 ( .A(n6400), .B(n4975), .Z(n6399));
+ IV2 U6481 ( .A(po038), .Z(n4975));
+ OR2 U6482 ( .A(n6401), .B(n3321), .Z(n6400));
+ AN2 U6483 ( .A(pi192), .B(n3943), .Z(n6401));
+ IV2 U6484 ( .A(pi050), .Z(n3943));
+ AN2 U6485 ( .A(po038), .B(n6402), .Z(n6398));
+ OR2 U6486 ( .A(n3940), .B(n3926), .Z(n6402));
+ AN2 U6487 ( .A(n3261), .B(pi050), .Z(n3940));
+ AN2 U6488 ( .A(n6403), .B(n4943), .Z(n6392));
+ IV2 U6489 ( .A(po057), .Z(n4943));
+ OR2 U6490 ( .A(n6404), .B(n6052), .Z(n6403));
+ OR2 U6491 ( .A(n6405), .B(n3926), .Z(n6052));
+ IV2 U6492 ( .A(n6155), .Z(n3926));
+ OR2 U6493 ( .A(pi192), .B(n3321), .Z(n6155));
+ AN2 U6494 ( .A(pi060), .B(n3989), .Z(n6405));
+ AN2 U6495 ( .A(n3989), .B(n3363), .Z(n6404));
+ IV2 U6496 ( .A(po027), .Z(n3363));
+ AN2 U6497 ( .A(n3261), .B(pi133), .Z(n3989));
+ IV2 U6498 ( .A(n3321), .Z(n3261));
+ IV2 U6499 ( .A(n6149), .Z(n4217));
+ OR2 U6500 ( .A(n4148), .B(n3321), .Z(n6149));
+ AN2 U6501 ( .A(pi161), .B(pi012), .Z(n3321));
+ IV2 U6502 ( .A(n4247), .Z(n4148));
+ OR2 U6503 ( .A(pi058), .B(n2837), .Z(n4247));
+ IV2 U6504 ( .A(pi192), .Z(n2837));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/C7552.ys b/examples/smtbmc/glift/C7552.ys
new file mode 100644
index 000000000..a9a1f5dc2
--- /dev/null
+++ b/examples/smtbmc/glift/C7552.ys
@@ -0,0 +1,41 @@
+read_verilog C7552.v
+techmap
+flatten
+select C7552_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename C7552_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog C7552.v
+techmap
+flatten
+select C7552_lev2
+glift -create-precise-model
+techmap
+opt
+rename C7552_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution C7552.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file C7552.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/examples/smtbmc/glift/C880.v b/examples/smtbmc/glift/C880.v
new file mode 100755
index 000000000..18dc24cc5
--- /dev/null
+++ b/examples/smtbmc/glift/C880.v
@@ -0,0 +1,451 @@
+module C880_lev2(pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23, pi24, pi25, pi26, pi27, pi28, pi29,
+ pi30, pi31, pi32, pi33, pi34, pi35, pi36, pi37, pi38, pi39,
+ pi40, pi41, pi42, pi43, pi44, pi45, pi46, pi47, pi48, pi49,
+ pi50, pi51, pi52, pi53, pi54, pi55, pi56, pi57, pi58, pi59,
+ po00, po01, po02, po03, po04, po05, po06, po07, po08, po09,
+ po10, po11, po12, po13, po14, po15, po16, po17, po18, po19,
+ po20, po21, po22, po23, po24, po25);
+
+input pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23, pi24, pi25, pi26, pi27, pi28, pi29,
+ pi30, pi31, pi32, pi33, pi34, pi35, pi36, pi37, pi38, pi39,
+ pi40, pi41, pi42, pi43, pi44, pi45, pi46, pi47, pi48, pi49,
+ pi50, pi51, pi52, pi53, pi54, pi55, pi56, pi57, pi58, pi59;
+
+output po00, po01, po02, po03, po04, po05, po06, po07, po08, po09,
+ po10, po11, po12, po13, po14, po15, po16, po17, po18, po19,
+ po20, po21, po22, po23, po24, po25;
+
+wire n137, n346, n364, n415, n295, n427, n351, n377, n454, n357,
+ n358, n359, n360, n361, n362, n363, n365, n366, n367, n368,
+ n369, n370, n371, n372, n373, n374, n375, n376, n378, n379,
+ n380, n381, n382, n383, n384, n385, n386, n387, n388, n389,
+ n390, n391, n392, n393, n394, n395, n396, n397, n398, n399,
+ n400, n401, n402, n403, n404, n405, n406, n407, n408, n409,
+ n410, n411, n412, n413, n414, n416, n417, n418, n419, n420,
+ n421, n422, n423, n424, n425, n426, n428, n429, n430, n431,
+ n432, n433, n434, n435, n436, n437, n438, n439, n440, n441,
+ n442, n443, n444, n445, n446, n447, n448, n449, n450, n451,
+ n452, n453, n455, n456, n457, n458, n459, n460, n461, n462,
+ n463, n464, n465, n466, n467, n468, n469, n470, n471, n472,
+ n473, n474, n475, n476, n477, n478, n479, n480, n481, n482,
+ n483, n484, n485, n486, n487, n488, n489, n490, n491, n492,
+ n493, n494, n495, n496, n497, n498, n499, n500, n501, n502,
+ n503, n504, n505, n506, n507, n508, n509, n510, n511, n512,
+ n513, n514, n515, n516, n517, n518, n519, n520, n521, n522,
+ n523, n524, n525, n526, n527, n528, n529, n530, n531, n532,
+ n533, n534, n535, n536, n537, n538, n539, n540, n541, n542,
+ n543, n544, n545, n546, n547, n548, n549, n550, n551, n552,
+ n553, n554, n555, n556, n557, n558, n559, n560, n561, n562,
+ n563, n564, n565, n566, n567, n568, n569, n570, n571, n572,
+ n573, n574, n575, n576, n577, n578, n579, n580, n581, n582,
+ n583, n584, n585, n586, n587, n588, n589, n590, n591, n592,
+ n593, n594, n595, n596, n597, n598, n599, n600, n601, n602,
+ n603, n604, n605, n606, n607, n608, n609, n610, n611, n612,
+ n613, n614, n615, n616, n617, n618, n619, n620, n621, n622,
+ n623, n624, n625, n626, n627, n628, n629, n630, n631, n632,
+ n633, n634, n635, n636, n637, n638, n639, n640, n641, n642,
+ n643, n644, n645, n646, n647, n648, n649, n650, n651, n652,
+ n653, n654, n655, n656, n657, n658, n659, n660, n661, n662,
+ n663, n664, n665, n666, n667, n668, n669, n670, n671, n672,
+ n673, n674, n675, n676, n677, n678, n679, n680, n681, n682,
+ n683, n684, n685, n686, n687, n688, n689, n690, n691, n692,
+ n693, n694, n695, n696;
+
+
+assign po22 = n137;
+assign po19 = n346;
+assign po16 = n364;
+assign po17 = n415;
+assign po18 = n295;
+assign po00 = n427;
+assign po09 = n351;
+assign po04 = n377;
+assign po06 = n454;
+ AN2 U371 ( .A(pi11), .B(pi08), .Z(n357));
+ AN2 U372 ( .A(pi28), .B(n357), .Z(n346));
+ AN2 U373 ( .A(pi41), .B(pi25), .Z(n369));
+ AN2 U374 ( .A(pi52), .B(n369), .Z(n361));
+ AN2 U375 ( .A(pi51), .B(pi54), .Z(n359));
+ AN2 U376 ( .A(pi28), .B(pi31), .Z(n604));
+ AN2 U377 ( .A(n604), .B(pi55), .Z(n358));
+ AN2 U378 ( .A(n359), .B(n358), .Z(n602));
+ AN2 U379 ( .A(pi53), .B(n602), .Z(n360));
+ AN2 U380 ( .A(n361), .B(n360), .Z(n577));
+ IV2 U381 ( .A(pi20), .Z(n607));
+ OR2 U382 ( .A(n607), .B(pi25), .Z(n362));
+ IV2 U383 ( .A(n362), .Z(n365));
+ AN2 U384 ( .A(pi25), .B(n607), .Z(n363));
+ OR2 U385 ( .A(n365), .B(n363), .Z(n367));
+ AN2 U386 ( .A(pi41), .B(pi24), .Z(n378));
+ AN2 U387 ( .A(n346), .B(n378), .Z(n366));
+ AN2 U388 ( .A(n367), .B(n366), .Z(n373));
+ AN2 U389 ( .A(pi28), .B(pi54), .Z(n368));
+ AN2 U390 ( .A(pi20), .B(n368), .Z(n603));
+ AN2 U391 ( .A(pi08), .B(n603), .Z(n371));
+ IV2 U392 ( .A(pi56), .Z(n694));
+ IV2 U393 ( .A(n369), .Z(n692));
+ OR2 U394 ( .A(n694), .B(n692), .Z(n370));
+ AN2 U395 ( .A(n371), .B(n370), .Z(n372));
+ OR2 U396 ( .A(n373), .B(n372), .Z(n424));
+ AN2 U397 ( .A(pi14), .B(n424), .Z(n384));
+ AN2 U398 ( .A(pi56), .B(pi48), .Z(n608));
+ AN2 U399 ( .A(n608), .B(n346), .Z(n374));
+ AN2 U400 ( .A(pi07), .B(n374), .Z(n376));
+ IV2 U401 ( .A(pi43), .Z(n375));
+ AN2 U402 ( .A(n376), .B(n375), .Z(n406));
+ AN2 U403 ( .A(pi20), .B(n406), .Z(n403));
+ IV2 U404 ( .A(n378), .Z(n379));
+ AN2 U405 ( .A(n346), .B(n379), .Z(n407));
+ AN2 U406 ( .A(pi55), .B(n407), .Z(n399));
+ AN2 U407 ( .A(pi44), .B(n399), .Z(n381));
+ AN2 U408 ( .A(pi37), .B(pi54), .Z(n380));
+ OR2 U409 ( .A(n381), .B(n380), .Z(n382));
+ OR2 U410 ( .A(n403), .B(n382), .Z(n383));
+ OR2 U411 ( .A(n384), .B(n383), .Z(n436));
+ AN2 U412 ( .A(pi26), .B(n436), .Z(n385));
+ OR2 U413 ( .A(n577), .B(n385), .Z(n386));
+ AN2 U414 ( .A(pi34), .B(n386), .Z(n448));
+ AN2 U415 ( .A(pi43), .B(pi05), .Z(n388));
+ AN2 U416 ( .A(pi32), .B(n436), .Z(n387));
+ OR2 U417 ( .A(n388), .B(n387), .Z(n446));
+ AN2 U418 ( .A(pi08), .B(pi37), .Z(n393));
+ AN2 U419 ( .A(pi50), .B(n399), .Z(n390));
+ AN2 U420 ( .A(pi18), .B(n424), .Z(n389));
+ OR2 U421 ( .A(n390), .B(n389), .Z(n391));
+ OR2 U422 ( .A(n403), .B(n391), .Z(n392));
+ OR2 U423 ( .A(n393), .B(n392), .Z(n494));
+ AN2 U424 ( .A(pi27), .B(n494), .Z(n497));
+ OR2 U425 ( .A(pi27), .B(n494), .Z(n499));
+ AN2 U426 ( .A(pi20), .B(pi37), .Z(n398));
+ AN2 U427 ( .A(pi45), .B(n399), .Z(n395));
+ AN2 U428 ( .A(pi22), .B(n424), .Z(n394));
+ OR2 U429 ( .A(n395), .B(n394), .Z(n396));
+ OR2 U430 ( .A(n403), .B(n396), .Z(n397));
+ OR2 U431 ( .A(n398), .B(n397), .Z(n536));
+ AN2 U432 ( .A(pi17), .B(n536), .Z(n539));
+ OR2 U433 ( .A(pi17), .B(n536), .Z(n541));
+ AN2 U434 ( .A(pi23), .B(n424), .Z(n405));
+ AN2 U435 ( .A(pi30), .B(pi37), .Z(n401));
+ AN2 U436 ( .A(pi29), .B(n399), .Z(n400));
+ OR2 U437 ( .A(n401), .B(n400), .Z(n402));
+ OR2 U438 ( .A(n403), .B(n402), .Z(n404));
+ OR2 U439 ( .A(n405), .B(n404), .Z(n579));
+ AN2 U440 ( .A(pi21), .B(n579), .Z(n582));
+ OR2 U441 ( .A(pi21), .B(n579), .Z(n584));
+ AN2 U442 ( .A(n406), .B(pi55), .Z(n429));
+ IV2 U443 ( .A(pi28), .Z(n409));
+ AN2 U444 ( .A(n407), .B(pi20), .Z(n408));
+ OR2 U445 ( .A(n409), .B(n408), .Z(n423));
+ AN2 U446 ( .A(pi50), .B(n423), .Z(n411));
+ AN2 U447 ( .A(pi42), .B(n424), .Z(n410));
+ OR2 U448 ( .A(n411), .B(n410), .Z(n412));
+ OR2 U449 ( .A(n429), .B(n412), .Z(n514));
+ AN2 U450 ( .A(pi15), .B(n514), .Z(n517));
+ OR2 U451 ( .A(pi15), .B(n514), .Z(n519));
+ AN2 U452 ( .A(pi45), .B(n423), .Z(n414));
+ AN2 U453 ( .A(pi40), .B(n424), .Z(n413));
+ OR2 U454 ( .A(n414), .B(n413), .Z(n416));
+ OR2 U455 ( .A(n429), .B(n416), .Z(n556));
+ AN2 U456 ( .A(pi03), .B(n556), .Z(n559));
+ OR2 U457 ( .A(pi03), .B(n556), .Z(n561));
+ AN2 U458 ( .A(pi29), .B(n423), .Z(n418));
+ AN2 U459 ( .A(pi04), .B(n424), .Z(n417));
+ OR2 U460 ( .A(n418), .B(n417), .Z(n419));
+ OR2 U461 ( .A(n429), .B(n419), .Z(n471));
+ AN2 U462 ( .A(pi10), .B(n471), .Z(n480));
+ OR2 U463 ( .A(pi10), .B(n471), .Z(n482));
+ AN2 U464 ( .A(pi46), .B(n482), .Z(n420));
+ OR2 U465 ( .A(n480), .B(n420), .Z(n562));
+ AN2 U466 ( .A(n561), .B(n562), .Z(n421));
+ OR2 U467 ( .A(n559), .B(n421), .Z(n520));
+ AN2 U468 ( .A(n519), .B(n520), .Z(n422));
+ OR2 U469 ( .A(n517), .B(n422), .Z(n449));
+ AN2 U470 ( .A(pi44), .B(n423), .Z(n426));
+ AN2 U471 ( .A(pi49), .B(n424), .Z(n425));
+ OR2 U472 ( .A(n426), .B(n425), .Z(n428));
+ OR2 U473 ( .A(n429), .B(n428), .Z(n464));
+ AN2 U474 ( .A(n449), .B(n464), .Z(n432));
+ OR2 U475 ( .A(n449), .B(n464), .Z(n430));
+ AN2 U476 ( .A(pi09), .B(n430), .Z(n431));
+ OR2 U477 ( .A(n432), .B(n431), .Z(n585));
+ AN2 U478 ( .A(n584), .B(n585), .Z(n433));
+ OR2 U479 ( .A(n582), .B(n433), .Z(n542));
+ AN2 U480 ( .A(n541), .B(n542), .Z(n434));
+ OR2 U481 ( .A(n539), .B(n434), .Z(n500));
+ AN2 U482 ( .A(n499), .B(n500), .Z(n435));
+ OR2 U483 ( .A(n497), .B(n435), .Z(n597));
+ OR2 U484 ( .A(pi34), .B(n436), .Z(n598));
+ AN2 U485 ( .A(n436), .B(pi34), .Z(n600));
+ IV2 U486 ( .A(n600), .Z(n437));
+ AN2 U487 ( .A(n598), .B(n437), .Z(n442));
+ OR2 U488 ( .A(n597), .B(n442), .Z(n440));
+ AN2 U489 ( .A(n597), .B(n442), .Z(n438));
+ IV2 U490 ( .A(n438), .Z(n439));
+ AN2 U491 ( .A(n440), .B(n439), .Z(n441));
+ AN2 U492 ( .A(pi12), .B(n441), .Z(n444));
+ AN2 U493 ( .A(n442), .B(pi19), .Z(n443));
+ OR2 U494 ( .A(n444), .B(n443), .Z(n445));
+ OR2 U495 ( .A(n446), .B(n445), .Z(n447));
+ OR2 U496 ( .A(n448), .B(n447), .Z(n137));
+ IV2 U497 ( .A(n464), .Z(n459));
+ AN2 U498 ( .A(pi12), .B(n449), .Z(n456));
+ AN2 U499 ( .A(n459), .B(n456), .Z(n453));
+ IV2 U500 ( .A(n449), .Z(n450));
+ AN2 U501 ( .A(n450), .B(pi12), .Z(n451));
+ OR2 U502 ( .A(pi19), .B(n451), .Z(n458));
+ AN2 U503 ( .A(n464), .B(n458), .Z(n452));
+ OR2 U504 ( .A(n453), .B(n452), .Z(n455));
+ IV2 U505 ( .A(pi09), .Z(n612));
+ AN2 U506 ( .A(n455), .B(n612), .Z(n470));
+ OR2 U507 ( .A(pi26), .B(n456), .Z(n457));
+ AN2 U508 ( .A(n464), .B(n457), .Z(n462));
+ AN2 U509 ( .A(n459), .B(n458), .Z(n460));
+ OR2 U510 ( .A(n577), .B(n460), .Z(n461));
+ OR2 U511 ( .A(n462), .B(n461), .Z(n463));
+ AN2 U512 ( .A(pi09), .B(n463), .Z(n468));
+ AN2 U513 ( .A(pi23), .B(pi05), .Z(n466));
+ AN2 U514 ( .A(pi32), .B(n464), .Z(n465));
+ OR2 U515 ( .A(n466), .B(n465), .Z(n467));
+ OR2 U516 ( .A(n468), .B(n467), .Z(n469));
+ OR2 U517 ( .A(n470), .B(n469), .Z(n295));
+ AN2 U518 ( .A(pi26), .B(n480), .Z(n479));
+ AN2 U519 ( .A(pi40), .B(pi05), .Z(n473));
+ AN2 U520 ( .A(pi32), .B(n471), .Z(n472));
+ OR2 U521 ( .A(n473), .B(n472), .Z(n477));
+ AN2 U522 ( .A(pi38), .B(pi36), .Z(n475));
+ AN2 U523 ( .A(pi10), .B(n577), .Z(n474));
+ OR2 U524 ( .A(n475), .B(n474), .Z(n476));
+ OR2 U525 ( .A(n477), .B(n476), .Z(n478));
+ OR2 U526 ( .A(n479), .B(n478), .Z(n491));
+ IV2 U527 ( .A(n480), .Z(n481));
+ AN2 U528 ( .A(n482), .B(n481), .Z(n487));
+ OR2 U529 ( .A(pi46), .B(n487), .Z(n485));
+ AN2 U530 ( .A(pi46), .B(n487), .Z(n483));
+ IV2 U531 ( .A(n483), .Z(n484));
+ AN2 U532 ( .A(n485), .B(n484), .Z(n486));
+ AN2 U533 ( .A(pi12), .B(n486), .Z(n489));
+ AN2 U534 ( .A(n487), .B(pi19), .Z(n488));
+ OR2 U535 ( .A(n489), .B(n488), .Z(n490));
+ OR2 U536 ( .A(n491), .B(n490), .Z(n351));
+ AN2 U537 ( .A(pi26), .B(n494), .Z(n492));
+ OR2 U538 ( .A(n577), .B(n492), .Z(n493));
+ AN2 U539 ( .A(pi27), .B(n493), .Z(n511));
+ AN2 U540 ( .A(pi14), .B(pi05), .Z(n496));
+ AN2 U541 ( .A(pi32), .B(n494), .Z(n495));
+ OR2 U542 ( .A(n496), .B(n495), .Z(n509));
+ IV2 U543 ( .A(n497), .Z(n498));
+ AN2 U544 ( .A(n499), .B(n498), .Z(n505));
+ OR2 U545 ( .A(n500), .B(n505), .Z(n503));
+ AN2 U546 ( .A(n500), .B(n505), .Z(n501));
+ IV2 U547 ( .A(n501), .Z(n502));
+ AN2 U548 ( .A(n503), .B(n502), .Z(n504));
+ AN2 U549 ( .A(pi12), .B(n504), .Z(n507));
+ AN2 U550 ( .A(n505), .B(pi19), .Z(n506));
+ OR2 U551 ( .A(n507), .B(n506), .Z(n508));
+ OR2 U552 ( .A(n509), .B(n508), .Z(n510));
+ OR2 U553 ( .A(n511), .B(n510), .Z(n364));
+ AN2 U554 ( .A(pi26), .B(n514), .Z(n512));
+ OR2 U555 ( .A(n577), .B(n512), .Z(n513));
+ AN2 U556 ( .A(pi15), .B(n513), .Z(n533));
+ AN2 U557 ( .A(pi49), .B(pi05), .Z(n531));
+ AN2 U558 ( .A(pi33), .B(pi36), .Z(n516));
+ AN2 U559 ( .A(pi32), .B(n514), .Z(n515));
+ OR2 U560 ( .A(n516), .B(n515), .Z(n529));
+ IV2 U561 ( .A(n517), .Z(n518));
+ AN2 U562 ( .A(n519), .B(n518), .Z(n525));
+ OR2 U563 ( .A(n520), .B(n525), .Z(n523));
+ AN2 U564 ( .A(n520), .B(n525), .Z(n521));
+ IV2 U565 ( .A(n521), .Z(n522));
+ AN2 U566 ( .A(n523), .B(n522), .Z(n524));
+ AN2 U567 ( .A(pi12), .B(n524), .Z(n527));
+ AN2 U568 ( .A(n525), .B(pi19), .Z(n526));
+ OR2 U569 ( .A(n527), .B(n526), .Z(n528));
+ OR2 U570 ( .A(n529), .B(n528), .Z(n530));
+ OR2 U571 ( .A(n531), .B(n530), .Z(n532));
+ OR2 U572 ( .A(n533), .B(n532), .Z(n377));
+ AN2 U573 ( .A(pi26), .B(n536), .Z(n534));
+ OR2 U574 ( .A(n577), .B(n534), .Z(n535));
+ AN2 U575 ( .A(pi17), .B(n535), .Z(n553));
+ AN2 U576 ( .A(pi18), .B(pi05), .Z(n538));
+ AN2 U577 ( .A(pi32), .B(n536), .Z(n537));
+ OR2 U578 ( .A(n538), .B(n537), .Z(n551));
+ IV2 U579 ( .A(n539), .Z(n540));
+ AN2 U580 ( .A(n541), .B(n540), .Z(n547));
+ OR2 U581 ( .A(n542), .B(n547), .Z(n545));
+ AN2 U582 ( .A(n542), .B(n547), .Z(n543));
+ IV2 U583 ( .A(n543), .Z(n544));
+ AN2 U584 ( .A(n545), .B(n544), .Z(n546));
+ AN2 U585 ( .A(pi12), .B(n546), .Z(n549));
+ AN2 U586 ( .A(n547), .B(pi19), .Z(n548));
+ OR2 U587 ( .A(n549), .B(n548), .Z(n550));
+ OR2 U588 ( .A(n551), .B(n550), .Z(n552));
+ OR2 U589 ( .A(n553), .B(n552), .Z(n415));
+ AN2 U590 ( .A(pi26), .B(n556), .Z(n554));
+ OR2 U591 ( .A(n577), .B(n554), .Z(n555));
+ AN2 U592 ( .A(pi03), .B(n555), .Z(n575));
+ AN2 U593 ( .A(pi42), .B(pi05), .Z(n573));
+ AN2 U594 ( .A(pi47), .B(pi36), .Z(n558));
+ AN2 U595 ( .A(pi32), .B(n556), .Z(n557));
+ OR2 U596 ( .A(n558), .B(n557), .Z(n571));
+ IV2 U597 ( .A(n559), .Z(n560));
+ AN2 U598 ( .A(n561), .B(n560), .Z(n567));
+ OR2 U599 ( .A(n562), .B(n567), .Z(n565));
+ AN2 U600 ( .A(n562), .B(n567), .Z(n563));
+ IV2 U601 ( .A(n563), .Z(n564));
+ AN2 U602 ( .A(n565), .B(n564), .Z(n566));
+ AN2 U603 ( .A(pi12), .B(n566), .Z(n569));
+ AN2 U604 ( .A(n567), .B(pi19), .Z(n568));
+ OR2 U605 ( .A(n569), .B(n568), .Z(n570));
+ OR2 U606 ( .A(n571), .B(n570), .Z(n572));
+ OR2 U607 ( .A(n573), .B(n572), .Z(n574));
+ OR2 U608 ( .A(n575), .B(n574), .Z(n427));
+ AN2 U609 ( .A(pi26), .B(n579), .Z(n576));
+ OR2 U610 ( .A(n577), .B(n576), .Z(n578));
+ AN2 U611 ( .A(pi21), .B(n578), .Z(n596));
+ AN2 U612 ( .A(pi22), .B(pi05), .Z(n581));
+ AN2 U613 ( .A(pi32), .B(n579), .Z(n580));
+ OR2 U614 ( .A(n581), .B(n580), .Z(n594));
+ IV2 U615 ( .A(n582), .Z(n583));
+ AN2 U616 ( .A(n584), .B(n583), .Z(n590));
+ OR2 U617 ( .A(n585), .B(n590), .Z(n588));
+ AN2 U618 ( .A(n585), .B(n590), .Z(n586));
+ IV2 U619 ( .A(n586), .Z(n587));
+ AN2 U620 ( .A(n588), .B(n587), .Z(n589));
+ AN2 U621 ( .A(pi12), .B(n589), .Z(n592));
+ AN2 U622 ( .A(n590), .B(pi19), .Z(n591));
+ OR2 U623 ( .A(n592), .B(n591), .Z(n593));
+ OR2 U624 ( .A(n594), .B(n593), .Z(n595));
+ OR2 U625 ( .A(n596), .B(n595), .Z(n454));
+ AN2 U626 ( .A(n598), .B(n597), .Z(n599));
+ OR2 U627 ( .A(n600), .B(n599), .Z(po07));
+ OR2 U628 ( .A(pi58), .B(pi00), .Z(n609));
+ AN2 U629 ( .A(pi59), .B(n609), .Z(po24));
+ AN2 U630 ( .A(n602), .B(pi57), .Z(n601));
+ AN2 U631 ( .A(pi41), .B(n601), .Z(po13));
+ AN2 U632 ( .A(pi48), .B(n602), .Z(po08));
+ AN2 U633 ( .A(n603), .B(pi31), .Z(po03));
+ AN2 U634 ( .A(pi48), .B(pi16), .Z(n610));
+ AN2 U635 ( .A(pi25), .B(n610), .Z(po25));
+ AN2 U636 ( .A(pi11), .B(n604), .Z(n605));
+ IV2 U637 ( .A(n605), .Z(n606));
+ OR2 U638 ( .A(n607), .B(n606), .Z(n691));
+ OR2 U639 ( .A(po25), .B(n691), .Z(po02));
+ AN2 U640 ( .A(n608), .B(pi25), .Z(po10));
+ AN2 U641 ( .A(pi13), .B(n609), .Z(po12));
+ AN2 U642 ( .A(pi07), .B(n610), .Z(po14));
+ IV2 U643 ( .A(pi15), .Z(n611));
+ AN2 U644 ( .A(pi09), .B(n611), .Z(n614));
+ AN2 U645 ( .A(pi15), .B(n612), .Z(n613));
+ OR2 U646 ( .A(n614), .B(n613), .Z(n618));
+ IV2 U647 ( .A(pi35), .Z(n654));
+ OR2 U648 ( .A(n654), .B(pi06), .Z(n617));
+ IV2 U649 ( .A(pi06), .Z(n615));
+ OR2 U650 ( .A(n615), .B(pi35), .Z(n616));
+ AN2 U651 ( .A(n617), .B(n616), .Z(n619));
+ OR2 U652 ( .A(n618), .B(n619), .Z(n622));
+ AN2 U653 ( .A(n619), .B(n618), .Z(n620));
+ IV2 U654 ( .A(n620), .Z(n621));
+ AN2 U655 ( .A(n622), .B(n621), .Z(n628));
+ IV2 U656 ( .A(pi10), .Z(n624));
+ OR2 U657 ( .A(n624), .B(pi03), .Z(n623));
+ IV2 U658 ( .A(n623), .Z(n626));
+ AN2 U659 ( .A(pi03), .B(n624), .Z(n625));
+ OR2 U660 ( .A(n626), .B(n625), .Z(n627));
+ OR2 U661 ( .A(n628), .B(n627), .Z(n631));
+ AN2 U662 ( .A(n628), .B(n627), .Z(n629));
+ IV2 U663 ( .A(n629), .Z(n630));
+ AN2 U664 ( .A(n631), .B(n630), .Z(n637));
+ IV2 U665 ( .A(pi34), .Z(n632));
+ AN2 U666 ( .A(pi27), .B(n632), .Z(n635));
+ OR2 U667 ( .A(n632), .B(pi27), .Z(n633));
+ IV2 U668 ( .A(n633), .Z(n634));
+ OR2 U669 ( .A(n635), .B(n634), .Z(n636));
+ OR2 U670 ( .A(n637), .B(n636), .Z(n640));
+ AN2 U671 ( .A(n637), .B(n636), .Z(n638));
+ IV2 U672 ( .A(n638), .Z(n639));
+ AN2 U673 ( .A(n640), .B(n639), .Z(n647));
+ IV2 U674 ( .A(pi21), .Z(n642));
+ OR2 U675 ( .A(n642), .B(pi17), .Z(n641));
+ IV2 U676 ( .A(n641), .Z(n644));
+ AN2 U677 ( .A(pi17), .B(n642), .Z(n643));
+ OR2 U678 ( .A(n644), .B(n643), .Z(n646));
+ OR2 U679 ( .A(n647), .B(n646), .Z(n645));
+ IV2 U680 ( .A(n645), .Z(n649));
+ AN2 U681 ( .A(n647), .B(n646), .Z(n648));
+ OR2 U682 ( .A(n649), .B(n648), .Z(po15));
+ IV2 U683 ( .A(pi42), .Z(n650));
+ AN2 U684 ( .A(pi49), .B(n650), .Z(n653));
+ IV2 U685 ( .A(pi49), .Z(n651));
+ AN2 U686 ( .A(pi42), .B(n651), .Z(n652));
+ OR2 U687 ( .A(n653), .B(n652), .Z(n658));
+ OR2 U688 ( .A(n654), .B(pi39), .Z(n657));
+ IV2 U689 ( .A(pi39), .Z(n655));
+ OR2 U690 ( .A(n655), .B(pi35), .Z(n656));
+ AN2 U691 ( .A(n657), .B(n656), .Z(n659));
+ OR2 U692 ( .A(n658), .B(n659), .Z(n662));
+ AN2 U693 ( .A(n659), .B(n658), .Z(n660));
+ IV2 U694 ( .A(n660), .Z(n661));
+ AN2 U695 ( .A(n662), .B(n661), .Z(n668));
+ IV2 U696 ( .A(pi04), .Z(n664));
+ OR2 U697 ( .A(n664), .B(pi18), .Z(n663));
+ IV2 U698 ( .A(n663), .Z(n666));
+ AN2 U699 ( .A(pi18), .B(n664), .Z(n665));
+ OR2 U700 ( .A(n666), .B(n665), .Z(n667));
+ OR2 U701 ( .A(n668), .B(n667), .Z(n671));
+ AN2 U702 ( .A(n668), .B(n667), .Z(n669));
+ IV2 U703 ( .A(n669), .Z(n670));
+ AN2 U704 ( .A(n671), .B(n670), .Z(n677));
+ IV2 U705 ( .A(pi22), .Z(n673));
+ OR2 U706 ( .A(n673), .B(pi14), .Z(n672));
+ IV2 U707 ( .A(n672), .Z(n675));
+ AN2 U708 ( .A(pi14), .B(n673), .Z(n674));
+ OR2 U709 ( .A(n675), .B(n674), .Z(n676));
+ OR2 U710 ( .A(n677), .B(n676), .Z(n680));
+ AN2 U711 ( .A(n677), .B(n676), .Z(n678));
+ IV2 U712 ( .A(n678), .Z(n679));
+ AN2 U713 ( .A(n680), .B(n679), .Z(n687));
+ IV2 U714 ( .A(pi40), .Z(n682));
+ OR2 U715 ( .A(n682), .B(pi23), .Z(n681));
+ IV2 U716 ( .A(n681), .Z(n684));
+ AN2 U717 ( .A(pi23), .B(n682), .Z(n683));
+ OR2 U718 ( .A(n684), .B(n683), .Z(n686));
+ OR2 U719 ( .A(n687), .B(n686), .Z(n685));
+ IV2 U720 ( .A(n685), .Z(n689));
+ AN2 U721 ( .A(n687), .B(n686), .Z(n688));
+ OR2 U722 ( .A(n689), .B(n688), .Z(po20));
+ AN2 U723 ( .A(pi01), .B(pi02), .Z(po21));
+ IV2 U724 ( .A(po25), .Z(n690));
+ OR2 U725 ( .A(n691), .B(n690), .Z(po23));
+ IV2 U726 ( .A(pi16), .Z(n696));
+ OR2 U727 ( .A(n692), .B(n696), .Z(po11));
+ AN2 U728 ( .A(pi07), .B(pi41), .Z(n693));
+ IV2 U729 ( .A(n693), .Z(n695));
+ OR2 U730 ( .A(n694), .B(n695), .Z(po01));
+ OR2 U731 ( .A(n696), .B(n695), .Z(po05));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/C880.ys b/examples/smtbmc/glift/C880.ys
new file mode 100644
index 000000000..410768f21
--- /dev/null
+++ b/examples/smtbmc/glift/C880.ys
@@ -0,0 +1,41 @@
+read_verilog C880.v
+techmap
+flatten
+select C880_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename C880_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog C880.v
+techmap
+flatten
+select C880_lev2
+glift -create-precise-model
+techmap
+opt
+rename C880_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution C880.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file C880.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/examples/smtbmc/glift/alu2.v b/examples/smtbmc/glift/alu2.v
new file mode 100755
index 000000000..6b6e3d7af
--- /dev/null
+++ b/examples/smtbmc/glift/alu2.v
@@ -0,0 +1,400 @@
+module alu2_lev2(pi0, pi1, pi2, pi3, pi4, pi5, pi6, pi7, pi8, pi9,
+ po0, po1, po2, po3, po4, po5);
+
+input pi0, pi1, pi2, pi3, pi4, pi5, pi6, pi7, pi8, pi9;
+
+output po0, po1, po2, po3, po4, po5;
+
+wire n358, n359, n360, n361, n362, n363, n364, n365, n366, n367,
+ n368, n369, n370, n371, n372, n373, n374, n375, n376, n377,
+ n378, n379, n380, n381, n382, n383, n384, n385, n386, n387,
+ n388, n389, n390, n391, n392, n393, n394, n395, n396, n397,
+ n398, n399, n400, n401, n402, n403, n404, n405, n406, n407,
+ n408, n409, n410, n411, n412, n413, n414, n415, n416, n417,
+ n418, n419, n420, n421, n422, n423, n424, n425, n426, n427,
+ n428, n429, n430, n431, n432, n433, n434, n435, n436, n437,
+ n438, n439, n440, n441, n442, n443, n444, n445, n446, n447,
+ n448, n449, n450, n451, n452, n453, n454, n455, n456, n457,
+ n458, n459, n460, n461, n462, n463, n464, n465, n466, n467,
+ n468, n469, n470, n471, n472, n473, n474, n475, n476, n477,
+ n478, n479, n480, n481, n482, n483, n484, n485, n486, n487,
+ n488, n489, n490, n491, n492, n493, n494, n495, n496, n497,
+ n498, n499, n500, n501, n502, n503, n504, n505, n506, n507,
+ n508, n509, n510, n511, n512, n513, n514, n515, n516, n517,
+ n518, n519, n520, n521, n522, n523, n524, n525, n526, n527,
+ n528, n529, n530, n531, n532, n533, n534, n535, n536, n537,
+ n538, n539, n540, n541, n542, n543, n544, n545, n546, n547,
+ n548, n549, n550, n551, n552, n553, n554, n555, n556, n557,
+ n558, n559, n560, n561, n562, n563, n564, n565, n566, n567,
+ n568, n569, n570, n571, n572, n573, n574, n575, n576, n577,
+ n578, n579, n580, n581, n582, n583, n584, n585, n586, n587,
+ n588, n589, n590, n591, n592, n593, n594, n595, n596, n597,
+ n598, n599, n600, n601, n602, n603, n604, n605, n606, n607,
+ n608, n609, n610, n611, n612, n613, n614, n615, n616, n617,
+ n618, n619, n620, n621, n622, n623, n624, n625, n626, n627,
+ n628, n629, n630, n631, n632, n633, n634, n635, n636, n637,
+ n638, n639, n640, n641, n642, n643, n644, n645, n646, n647,
+ n648, n649, n650, n651, n652, n653, n654, n655, n656, n657,
+ n658, n659, n660, n661, n662, n663, n664, n665, n666, n667,
+ n668, n669, n670, n671, n672, n673, n674, n675, n676, n677,
+ n678, n679, n680, n681, n682, n683, n684, n685, n686, n687;
+
+ AN2 U363 ( .A(n358), .B(po2), .Z(po5));
+ OR2 U364 ( .A(n359), .B(n360), .Z(n358));
+ AN2 U365 ( .A(n361), .B(n362), .Z(n359));
+ AN2 U366 ( .A(pi9), .B(n363), .Z(po4));
+ OR2 U367 ( .A(n364), .B(n365), .Z(n363));
+ OR2 U368 ( .A(n366), .B(n367), .Z(n365));
+ AN2 U369 ( .A(pi6), .B(n368), .Z(n367));
+ OR2 U370 ( .A(n369), .B(n370), .Z(n368));
+ OR2 U371 ( .A(n371), .B(n372), .Z(n370));
+ OR2 U372 ( .A(n373), .B(n374), .Z(n372));
+ AN2 U373 ( .A(n375), .B(n376), .Z(n374));
+ AN2 U374 ( .A(n377), .B(n378), .Z(n375));
+ OR2 U375 ( .A(n379), .B(n380), .Z(n377));
+ OR2 U376 ( .A(n381), .B(n382), .Z(n380));
+ OR2 U377 ( .A(n383), .B(n384), .Z(n379));
+ AN2 U378 ( .A(n385), .B(pi5), .Z(n384));
+ AN2 U379 ( .A(n386), .B(n387), .Z(n383));
+ AN2 U380 ( .A(pi4), .B(n361), .Z(n386));
+ AN2 U381 ( .A(n388), .B(n389), .Z(n373));
+ OR2 U382 ( .A(n390), .B(n391), .Z(n388));
+ AN2 U383 ( .A(pi1), .B(n392), .Z(n390));
+ OR2 U384 ( .A(n393), .B(n394), .Z(n392));
+ OR2 U385 ( .A(pi7), .B(n395), .Z(n394));
+ AN2 U386 ( .A(n381), .B(n396), .Z(n395));
+ OR2 U387 ( .A(n397), .B(n398), .Z(n369));
+ AN2 U388 ( .A(n399), .B(n400), .Z(n398));
+ AN2 U389 ( .A(n387), .B(n401), .Z(n399));
+ AN2 U390 ( .A(n402), .B(n403), .Z(n397));
+ AN2 U391 ( .A(pi0), .B(n404), .Z(n402));
+ OR2 U392 ( .A(pi1), .B(n389), .Z(n404));
+ AN2 U393 ( .A(n405), .B(n406), .Z(n366));
+ OR2 U394 ( .A(n407), .B(n408), .Z(n406));
+ AN2 U395 ( .A(n360), .B(n409), .Z(n408));
+ OR2 U396 ( .A(n410), .B(n411), .Z(n409));
+ OR2 U397 ( .A(n412), .B(n413), .Z(n411));
+ AN2 U398 ( .A(n414), .B(pi3), .Z(n413));
+ AN2 U399 ( .A(n389), .B(n415), .Z(n410));
+ AN2 U400 ( .A(po3), .B(n416), .Z(n407));
+ OR2 U401 ( .A(n417), .B(n414), .Z(n416));
+ OR2 U402 ( .A(n418), .B(n419), .Z(n364));
+ OR2 U403 ( .A(n420), .B(n421), .Z(n419));
+ AN2 U404 ( .A(n422), .B(n382), .Z(n421));
+ AN2 U405 ( .A(pi7), .B(n389), .Z(n422));
+ AN2 U406 ( .A(n423), .B(n424), .Z(n418));
+ AN2 U407 ( .A(n425), .B(n426), .Z(n423));
+ OR2 U408 ( .A(n427), .B(po3), .Z(po2));
+ AN2 U409 ( .A(n428), .B(n429), .Z(n427));
+ OR2 U410 ( .A(n430), .B(n431), .Z(po1));
+ AN2 U411 ( .A(pi9), .B(n432), .Z(n431));
+ OR2 U412 ( .A(n433), .B(n434), .Z(n432));
+ OR2 U413 ( .A(n435), .B(n436), .Z(n434));
+ AN2 U414 ( .A(n437), .B(n438), .Z(n436));
+ IV2 U415 ( .A(n425), .Z(n438));
+ AN2 U416 ( .A(n424), .B(n426), .Z(n437));
+ OR2 U417 ( .A(n439), .B(n440), .Z(n424));
+ OR2 U418 ( .A(n441), .B(n442), .Z(n440));
+ AN2 U419 ( .A(n381), .B(n443), .Z(n442));
+ OR2 U420 ( .A(n444), .B(n445), .Z(n443));
+ AN2 U421 ( .A(n446), .B(n447), .Z(n441));
+ AN2 U422 ( .A(n387), .B(n361), .Z(n446));
+ AN2 U423 ( .A(n448), .B(n425), .Z(n435));
+ OR2 U424 ( .A(n449), .B(n450), .Z(n425));
+ OR2 U425 ( .A(n420), .B(n451), .Z(n450));
+ OR2 U426 ( .A(n452), .B(n453), .Z(n451));
+ AN2 U427 ( .A(pi6), .B(n454), .Z(n453));
+ OR2 U428 ( .A(n371), .B(n455), .Z(n454));
+ AN2 U429 ( .A(n376), .B(n456), .Z(n455));
+ OR2 U430 ( .A(n457), .B(n458), .Z(n456));
+ OR2 U431 ( .A(n459), .B(n460), .Z(n458));
+ AN2 U432 ( .A(n461), .B(n378), .Z(n460));
+ OR2 U433 ( .A(n462), .B(n463), .Z(n461));
+ AN2 U434 ( .A(n385), .B(n464), .Z(n462));
+ OR2 U435 ( .A(n465), .B(pi5), .Z(n464));
+ AN2 U436 ( .A(pi7), .B(n466), .Z(n459));
+ OR2 U437 ( .A(n467), .B(n468), .Z(n466));
+ OR2 U438 ( .A(n469), .B(n470), .Z(n468));
+ AN2 U439 ( .A(n381), .B(pi1), .Z(n470));
+ AN2 U440 ( .A(n471), .B(n428), .Z(n469));
+ AN2 U441 ( .A(pi0), .B(n387), .Z(n471));
+ AN2 U442 ( .A(n412), .B(n361), .Z(n467));
+ AN2 U443 ( .A(n472), .B(n473), .Z(n457));
+ AN2 U444 ( .A(n360), .B(n428), .Z(n472));
+ AN2 U445 ( .A(n463), .B(n428), .Z(n371));
+ AN2 U446 ( .A(n474), .B(n475), .Z(n452));
+ OR2 U447 ( .A(n476), .B(n477), .Z(n474));
+ OR2 U448 ( .A(n478), .B(n479), .Z(n477));
+ AN2 U449 ( .A(n480), .B(n428), .Z(n479));
+ AN2 U450 ( .A(n481), .B(n482), .Z(n480));
+ OR2 U451 ( .A(n360), .B(n389), .Z(n482));
+ OR2 U452 ( .A(n401), .B(n483), .Z(n481));
+ AN2 U453 ( .A(pi7), .B(n484), .Z(n483));
+ OR2 U454 ( .A(n393), .B(n485), .Z(n484));
+ AN2 U455 ( .A(n376), .B(n415), .Z(n485));
+ AN2 U456 ( .A(n414), .B(n429), .Z(n393));
+ AN2 U457 ( .A(n486), .B(n378), .Z(n478));
+ OR2 U458 ( .A(n412), .B(n389), .Z(n486));
+ AN2 U459 ( .A(n487), .B(pi1), .Z(n412));
+ OR2 U460 ( .A(n488), .B(n489), .Z(n476));
+ AN2 U461 ( .A(n490), .B(n401), .Z(n488));
+ AN2 U462 ( .A(pi1), .B(n429), .Z(n490));
+ AN2 U463 ( .A(n385), .B(n491), .Z(n420));
+ IV2 U464 ( .A(n492), .Z(n491));
+ OR2 U465 ( .A(n493), .B(n487), .Z(n492));
+ AN2 U466 ( .A(n494), .B(n495), .Z(n493));
+ OR2 U467 ( .A(pi6), .B(n389), .Z(n495));
+ OR2 U468 ( .A(pi7), .B(pi1), .Z(n494));
+ OR2 U469 ( .A(n496), .B(n497), .Z(n449));
+ AN2 U470 ( .A(n498), .B(n376), .Z(n497));
+ AN2 U471 ( .A(n381), .B(n382), .Z(n498));
+ AN2 U472 ( .A(n499), .B(n389), .Z(n496));
+ OR2 U473 ( .A(n500), .B(n501), .Z(n499));
+ OR2 U474 ( .A(n502), .B(n503), .Z(n501));
+ AN2 U475 ( .A(n385), .B(n504), .Z(n503));
+ OR2 U476 ( .A(n505), .B(n506), .Z(n504));
+ AN2 U477 ( .A(po3), .B(n400), .Z(n506));
+ AN2 U478 ( .A(n507), .B(n428), .Z(n505));
+ AN2 U479 ( .A(n508), .B(n387), .Z(n502));
+ OR2 U480 ( .A(n509), .B(n510), .Z(n508));
+ OR2 U481 ( .A(n489), .B(n511), .Z(n510));
+ OR2 U482 ( .A(n465), .B(n512), .Z(n511));
+ AN2 U483 ( .A(n513), .B(pi1), .Z(n512));
+ AN2 U484 ( .A(pi0), .B(n514), .Z(n513));
+ OR2 U485 ( .A(n507), .B(n515), .Z(n514));
+ AN2 U486 ( .A(n361), .B(n428), .Z(n465));
+ AN2 U487 ( .A(po3), .B(n360), .Z(n489));
+ OR2 U488 ( .A(n516), .B(n517), .Z(n509));
+ OR2 U489 ( .A(n518), .B(n519), .Z(n517));
+ AN2 U490 ( .A(n391), .B(n362), .Z(n519));
+ AN2 U491 ( .A(n428), .B(n400), .Z(n391));
+ AN2 U492 ( .A(n520), .B(n521), .Z(n518));
+ OR2 U493 ( .A(n522), .B(n362), .Z(n521));
+ AN2 U494 ( .A(n429), .B(n523), .Z(n520));
+ AN2 U495 ( .A(n417), .B(n378), .Z(n516));
+ AN2 U496 ( .A(n522), .B(n382), .Z(n500));
+ AN2 U497 ( .A(pi1), .B(n396), .Z(n382));
+ AN2 U498 ( .A(n361), .B(n378), .Z(n522));
+ OR2 U499 ( .A(n524), .B(n525), .Z(n448));
+ OR2 U500 ( .A(n526), .B(n527), .Z(n525));
+ OR2 U501 ( .A(pi8), .B(n528), .Z(n524));
+ AN2 U502 ( .A(n529), .B(n530), .Z(n430));
+ OR2 U503 ( .A(n531), .B(n532), .Z(n529));
+ OR2 U504 ( .A(n533), .B(n534), .Z(n532));
+ OR2 U505 ( .A(n535), .B(n536), .Z(n534));
+ AN2 U506 ( .A(n537), .B(n376), .Z(n536));
+ IV2 U507 ( .A(n389), .Z(n376));
+ AN2 U508 ( .A(n538), .B(n389), .Z(n535));
+ OR2 U509 ( .A(n539), .B(n540), .Z(n389));
+ OR2 U510 ( .A(n541), .B(n542), .Z(n540));
+ OR2 U511 ( .A(n543), .B(n544), .Z(n542));
+ AN2 U512 ( .A(pi1), .B(n545), .Z(n544));
+ AN2 U513 ( .A(n546), .B(n428), .Z(n543));
+ AN2 U514 ( .A(n547), .B(n548), .Z(n546));
+ OR2 U515 ( .A(pi3), .B(n396), .Z(n548));
+ AN2 U516 ( .A(pi9), .B(n549), .Z(n541));
+ OR2 U517 ( .A(n550), .B(n551), .Z(n549));
+ OR2 U518 ( .A(n552), .B(n553), .Z(n551));
+ AN2 U519 ( .A(n554), .B(n507), .Z(n553));
+ AN2 U520 ( .A(n396), .B(pi0), .Z(n554));
+ AN2 U521 ( .A(n555), .B(n556), .Z(n552));
+ AN2 U522 ( .A(n557), .B(n415), .Z(n556));
+ AN2 U523 ( .A(po3), .B(n558), .Z(n555));
+ OR2 U524 ( .A(n559), .B(n560), .Z(n550));
+ AN2 U525 ( .A(n561), .B(n429), .Z(n560));
+ AN2 U526 ( .A(n417), .B(n562), .Z(n561));
+ OR2 U527 ( .A(n563), .B(n564), .Z(n562));
+ AN2 U528 ( .A(n558), .B(n428), .Z(n564));
+ AN2 U529 ( .A(pi1), .B(n565), .Z(n563));
+ AN2 U530 ( .A(pi3), .B(n566), .Z(n559));
+ OR2 U531 ( .A(n567), .B(n414), .Z(n566));
+ AN2 U532 ( .A(n568), .B(n569), .Z(n567));
+ AN2 U533 ( .A(n565), .B(n428), .Z(n568));
+ OR2 U534 ( .A(n570), .B(n571), .Z(n539));
+ AN2 U535 ( .A(n572), .B(n429), .Z(n571));
+ AN2 U536 ( .A(po3), .B(n573), .Z(n570));
+ OR2 U537 ( .A(n574), .B(n575), .Z(n538));
+ OR2 U538 ( .A(n445), .B(n576), .Z(n575));
+ AN2 U539 ( .A(n577), .B(pi3), .Z(n576));
+ AN2 U540 ( .A(n578), .B(pi1), .Z(n574));
+ AN2 U541 ( .A(n507), .B(pi1), .Z(n533));
+ OR2 U542 ( .A(n579), .B(n580), .Z(n531));
+ OR2 U543 ( .A(n581), .B(n582), .Z(n580));
+ AN2 U544 ( .A(n444), .B(po3), .Z(n582));
+ AN2 U545 ( .A(pi1), .B(pi3), .Z(po3));
+ AN2 U546 ( .A(n583), .B(n557), .Z(n581));
+ AN2 U547 ( .A(n584), .B(n429), .Z(n583));
+ OR2 U548 ( .A(n585), .B(n414), .Z(n584));
+ AN2 U549 ( .A(n417), .B(n428), .Z(n585));
+ AN2 U550 ( .A(n586), .B(pi7), .Z(n579));
+ AN2 U551 ( .A(n587), .B(n588), .Z(n586));
+ OR2 U552 ( .A(pi3), .B(n589), .Z(n588));
+ AN2 U553 ( .A(pi1), .B(n523), .Z(n589));
+ OR2 U554 ( .A(n429), .B(n590), .Z(n587));
+ OR2 U555 ( .A(n417), .B(n591), .Z(n590));
+ AN2 U556 ( .A(n592), .B(n428), .Z(n591));
+ IV2 U557 ( .A(pi1), .Z(n428));
+ IV2 U558 ( .A(pi3), .Z(n429));
+ OR2 U559 ( .A(n593), .B(n594), .Z(po0));
+ OR2 U560 ( .A(n595), .B(n596), .Z(n594));
+ AN2 U561 ( .A(n597), .B(pi8), .Z(n596));
+ AN2 U562 ( .A(n598), .B(n381), .Z(n597));
+ AN2 U563 ( .A(pi0), .B(n385), .Z(n381));
+ AN2 U564 ( .A(n507), .B(n487), .Z(n598));
+ AN2 U565 ( .A(n528), .B(n426), .Z(n595));
+ AN2 U566 ( .A(pi6), .B(n599), .Z(n528));
+ IV2 U567 ( .A(n600), .Z(n599));
+ OR2 U568 ( .A(n601), .B(n361), .Z(n600));
+ AN2 U569 ( .A(n602), .B(n603), .Z(n601));
+ AN2 U570 ( .A(n604), .B(n605), .Z(n603));
+ OR2 U571 ( .A(pi7), .B(n606), .Z(n605));
+ OR2 U572 ( .A(n607), .B(n387), .Z(n606));
+ OR2 U573 ( .A(n378), .B(n487), .Z(n604));
+ AN2 U574 ( .A(n608), .B(n609), .Z(n602));
+ OR2 U575 ( .A(pi2), .B(n415), .Z(n608));
+ OR2 U576 ( .A(n610), .B(n611), .Z(n593));
+ AN2 U577 ( .A(pi9), .B(n612), .Z(n611));
+ OR2 U578 ( .A(n613), .B(n614), .Z(n612));
+ OR2 U579 ( .A(n433), .B(n615), .Z(n614));
+ AN2 U580 ( .A(n527), .B(n426), .Z(n615));
+ OR2 U581 ( .A(n616), .B(n617), .Z(n527));
+ AN2 U582 ( .A(n618), .B(n361), .Z(n617));
+ OR2 U583 ( .A(n619), .B(n620), .Z(n618));
+ OR2 U584 ( .A(n621), .B(n622), .Z(n620));
+ AN2 U585 ( .A(n592), .B(n362), .Z(n622));
+ AN2 U586 ( .A(n385), .B(n623), .Z(n621));
+ OR2 U587 ( .A(n624), .B(n625), .Z(n623));
+ AN2 U588 ( .A(n626), .B(n415), .Z(n625));
+ AN2 U589 ( .A(n507), .B(n523), .Z(n624));
+ AN2 U590 ( .A(n473), .B(n557), .Z(n619));
+ AN2 U591 ( .A(n523), .B(n387), .Z(n473));
+ AN2 U592 ( .A(n569), .B(n387), .Z(n616));
+ AN2 U593 ( .A(n578), .B(n627), .Z(n433));
+ AN2 U594 ( .A(n378), .B(n475), .Z(n627));
+ OR2 U595 ( .A(n628), .B(n629), .Z(n613));
+ AN2 U596 ( .A(n526), .B(n426), .Z(n629));
+ IV2 U597 ( .A(pi8), .Z(n426));
+ AN2 U598 ( .A(n360), .B(n405), .Z(n526));
+ AN2 U599 ( .A(pi8), .B(n630), .Z(n628));
+ OR2 U600 ( .A(n631), .B(n439), .Z(n630));
+ OR2 U601 ( .A(n632), .B(n633), .Z(n439));
+ OR2 U602 ( .A(n634), .B(n635), .Z(n633));
+ AN2 U603 ( .A(n636), .B(n378), .Z(n635));
+ OR2 U604 ( .A(n637), .B(n360), .Z(n636));
+ AN2 U605 ( .A(n387), .B(n475), .Z(n637));
+ AN2 U606 ( .A(n638), .B(n475), .Z(n634));
+ OR2 U607 ( .A(n639), .B(n640), .Z(n638));
+ AN2 U608 ( .A(n558), .B(pi4), .Z(n639));
+ OR2 U609 ( .A(n463), .B(n641), .Z(n632));
+ AN2 U610 ( .A(n642), .B(n385), .Z(n641));
+ AN2 U611 ( .A(n557), .B(n361), .Z(n642));
+ AN2 U612 ( .A(n361), .B(n578), .Z(n463));
+ AN2 U613 ( .A(n403), .B(n361), .Z(n631));
+ IV2 U614 ( .A(n609), .Z(n403));
+ OR2 U615 ( .A(n385), .B(n378), .Z(n609));
+ AN2 U616 ( .A(n643), .B(n530), .Z(n610));
+ OR2 U617 ( .A(n644), .B(n645), .Z(n643));
+ OR2 U618 ( .A(n646), .B(n647), .Z(n645));
+ OR2 U619 ( .A(n648), .B(n649), .Z(n647));
+ AN2 U620 ( .A(n537), .B(n385), .Z(n649));
+ IV2 U621 ( .A(n387), .Z(n385));
+ OR2 U622 ( .A(n650), .B(n651), .Z(n537));
+ AN2 U623 ( .A(n396), .B(pi6), .Z(n651));
+ AN2 U624 ( .A(n400), .B(n475), .Z(n650));
+ AN2 U625 ( .A(n652), .B(n387), .Z(n648));
+ OR2 U626 ( .A(n653), .B(n654), .Z(n387));
+ OR2 U627 ( .A(n655), .B(n656), .Z(n654));
+ OR2 U628 ( .A(n657), .B(n658), .Z(n656));
+ AN2 U629 ( .A(n360), .B(n573), .Z(n658));
+ OR2 U630 ( .A(n659), .B(n660), .Z(n573));
+ AN2 U631 ( .A(n405), .B(n578), .Z(n660));
+ AN2 U632 ( .A(n396), .B(n661), .Z(n659));
+ OR2 U633 ( .A(n405), .B(n557), .Z(n661));
+ AN2 U634 ( .A(n475), .B(pi7), .Z(n405));
+ IV2 U635 ( .A(n607), .Z(n396));
+ OR2 U636 ( .A(pi5), .B(pi4), .Z(n607));
+ AN2 U637 ( .A(n640), .B(n417), .Z(n657));
+ AN2 U638 ( .A(n572), .B(n362), .Z(n655));
+ OR2 U639 ( .A(n662), .B(n663), .Z(n572));
+ OR2 U640 ( .A(n664), .B(n665), .Z(n663));
+ AN2 U641 ( .A(n578), .B(n557), .Z(n665));
+ AN2 U642 ( .A(n417), .B(n626), .Z(n664));
+ AN2 U643 ( .A(n507), .B(n530), .Z(n662));
+ OR2 U644 ( .A(n666), .B(n667), .Z(n653));
+ OR2 U645 ( .A(n668), .B(n669), .Z(n667));
+ AN2 U646 ( .A(n670), .B(n545), .Z(n669));
+ OR2 U647 ( .A(n400), .B(n671), .Z(n545));
+ AN2 U648 ( .A(pi9), .B(n414), .Z(n671));
+ AN2 U649 ( .A(n378), .B(n414), .Z(n400));
+ IV2 U650 ( .A(pi7), .Z(n378));
+ OR2 U651 ( .A(pi0), .B(pi2), .Z(n670));
+ AN2 U652 ( .A(n672), .B(n547), .Z(n668));
+ AN2 U653 ( .A(n475), .B(n530), .Z(n547));
+ IV2 U654 ( .A(pi9), .Z(n530));
+ AN2 U655 ( .A(n361), .B(n415), .Z(n672));
+ AN2 U656 ( .A(n558), .B(n569), .Z(n666));
+ AN2 U657 ( .A(n557), .B(n417), .Z(n569));
+ OR2 U658 ( .A(n673), .B(n674), .Z(n652));
+ OR2 U659 ( .A(n445), .B(n675), .Z(n674));
+ AN2 U660 ( .A(n577), .B(pi2), .Z(n675));
+ AN2 U661 ( .A(n523), .B(n447), .Z(n445));
+ OR2 U662 ( .A(n577), .B(n507), .Z(n447));
+ AN2 U663 ( .A(n475), .B(n415), .Z(n577));
+ AN2 U664 ( .A(n578), .B(pi0), .Z(n673));
+ IV2 U665 ( .A(n487), .Z(n578));
+ OR2 U666 ( .A(n415), .B(n523), .Z(n487));
+ AN2 U667 ( .A(n507), .B(pi0), .Z(n646));
+ AN2 U668 ( .A(pi6), .B(pi7), .Z(n507));
+ OR2 U669 ( .A(n676), .B(n677), .Z(n644));
+ OR2 U670 ( .A(n678), .B(n679), .Z(n677));
+ AN2 U671 ( .A(n444), .B(n360), .Z(n679));
+ IV2 U672 ( .A(n401), .Z(n360));
+ OR2 U673 ( .A(n362), .B(n361), .Z(n401));
+ AN2 U674 ( .A(pi6), .B(n417), .Z(n444));
+ AN2 U675 ( .A(n680), .B(n557), .Z(n678));
+ IV2 U676 ( .A(n626), .Z(n557));
+ OR2 U677 ( .A(pi7), .B(n475), .Z(n626));
+ AN2 U678 ( .A(n681), .B(n362), .Z(n680));
+ OR2 U679 ( .A(n682), .B(n414), .Z(n681));
+ AN2 U680 ( .A(n417), .B(n361), .Z(n682));
+ IV2 U681 ( .A(pi0), .Z(n361));
+ AN2 U682 ( .A(pi7), .B(n683), .Z(n676));
+ OR2 U683 ( .A(n684), .B(n685), .Z(n683));
+ OR2 U684 ( .A(n686), .B(n687), .Z(n685));
+ AN2 U685 ( .A(n592), .B(n558), .Z(n687));
+ IV2 U686 ( .A(n565), .Z(n558));
+ OR2 U687 ( .A(pi0), .B(n362), .Z(n565));
+ AN2 U688 ( .A(n475), .B(n414), .Z(n592));
+ IV2 U689 ( .A(n515), .Z(n414));
+ OR2 U690 ( .A(pi5), .B(n415), .Z(n515));
+ IV2 U691 ( .A(pi6), .Z(n475));
+ AN2 U692 ( .A(n640), .B(n523), .Z(n686));
+ IV2 U693 ( .A(pi5), .Z(n523));
+ AN2 U694 ( .A(n362), .B(pi0), .Z(n640));
+ IV2 U695 ( .A(pi2), .Z(n362));
+ AN2 U696 ( .A(n417), .B(pi2), .Z(n684));
+ AN2 U697 ( .A(n415), .B(pi5), .Z(n417));
+ IV2 U698 ( .A(pi4), .Z(n415));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/alu2.ys b/examples/smtbmc/glift/alu2.ys
new file mode 100644
index 000000000..b1671752e
--- /dev/null
+++ b/examples/smtbmc/glift/alu2.ys
@@ -0,0 +1,41 @@
+read_verilog alu2.v
+techmap
+flatten
+select alu2_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename alu2_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog alu2.v
+techmap
+flatten
+select alu2_lev2
+glift -create-precise-model
+techmap
+opt
+rename alu2_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution alu2.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file alu2.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/examples/smtbmc/glift/alu4.v b/examples/smtbmc/glift/alu4.v
new file mode 100755
index 000000000..e110612e5
--- /dev/null
+++ b/examples/smtbmc/glift/alu4.v
@@ -0,0 +1,802 @@
+module alu4_lev2(pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, po0, po1, po2, po3, po4, po5, po6, po7);
+
+input pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13;
+
+output po0, po1, po2, po3, po4, po5, po6, po7;
+
+wire n705, n706, n707, n708, n709, n710, n711, n712, n713, n714,
+ n715, n716, n717, n718, n719, n720, n721, n722, n723, n724,
+ n725, n726, n727, n728, n729, n730, n731, n732, n733, n734,
+ n735, n736, n737, n738, n739, n740, n741, n742, n743, n744,
+ n745, n746, n747, n748, n749, n750, n751, n752, n753, n754,
+ n755, n756, n757, n758, n759, n760, n761, n762, n763, n764,
+ n765, n766, n767, n768, n769, n770, n771, n772, n773, n774,
+ n775, n776, n777, n778, n779, n780, n781, n782, n783, n784,
+ n785, n786, n787, n788, n789, n790, n791, n792, n793, n794,
+ n795, n796, n797, n798, n799, n800, n801, n802, n803, n804,
+ n805, n806, n807, n808, n809, n810, n811, n812, n813, n814,
+ n815, n816, n817, n818, n819, n820, n821, n822, n823, n824,
+ n825, n826, n827, n828, n829, n830, n831, n832, n833, n834,
+ n835, n836, n837, n838, n839, n840, n841, n842, n843, n844,
+ n845, n846, n847, n848, n849, n850, n851, n852, n853, n854,
+ n855, n856, n857, n858, n859, n860, n861, n862, n863, n864,
+ n865, n866, n867, n868, n869, n870, n871, n872, n873, n874,
+ n875, n876, n877, n878, n879, n880, n881, n882, n883, n884,
+ n885, n886, n887, n888, n889, n890, n891, n892, n893, n894,
+ n895, n896, n897, n898, n899, n900, n901, n902, n903, n904,
+ n905, n906, n907, n908, n909, n910, n911, n912, n913, n914,
+ n915, n916, n917, n918, n919, n920, n921, n922, n923, n924,
+ n925, n926, n927, n928, n929, n930, n931, n932, n933, n934,
+ n935, n936, n937, n938, n939, n940, n941, n942, n943, n944,
+ n945, n946, n947, n948, n949, n950, n951, n952, n953, n954,
+ n955, n956, n957, n958, n959, n960, n961, n962, n963, n964,
+ n965, n966, n967, n968, n969, n970, n971, n972, n973, n974,
+ n975, n976, n977, n978, n979, n980, n981, n982, n983, n984,
+ n985, n986, n987, n988, n989, n990, n991, n992, n993, n994,
+ n995, n996, n997, n998, n999, n1000, n1001, n1002, n1003, n1004,
+ n1005, n1006, n1007, n1008, n1009, n1010, n1011, n1012, n1013, n1014,
+ n1015, n1016, n1017, n1018, n1019, n1020, n1021, n1022, n1023, n1024,
+ n1025, n1026, n1027, n1028, n1029, n1030, n1031, n1032, n1033, n1034,
+ n1035, n1036, n1037, n1038, n1039, n1040, n1041, n1042, n1043, n1044,
+ n1045, n1046, n1047, n1048, n1049, n1050, n1051, n1052, n1053, n1054,
+ n1055, n1056, n1057, n1058, n1059, n1060, n1061, n1062, n1063, n1064,
+ n1065, n1066, n1067, n1068, n1069, n1070, n1071, n1072, n1073, n1074,
+ n1075, n1076, n1077, n1078, n1079, n1080, n1081, n1082, n1083, n1084,
+ n1085, n1086, n1087, n1088, n1089, n1090, n1091, n1092, n1093, n1094,
+ n1095, n1096, n1097, n1098, n1099, n1100, n1101, n1102, n1103, n1104,
+ n1105, n1106, n1107, n1108, n1109, n1110, n1111, n1112, n1113, n1114,
+ n1115, n1116, n1117, n1118, n1119, n1120, n1121, n1122, n1123, n1124,
+ n1125, n1126, n1127, n1128, n1129, n1130, n1131, n1132, n1133, n1134,
+ n1135, n1136, n1137, n1138, n1139, n1140, n1141, n1142, n1143, n1144,
+ n1145, n1146, n1147, n1148, n1149, n1150, n1151, n1152, n1153, n1154,
+ n1155, n1156, n1157, n1158, n1159, n1160, n1161, n1162, n1163, n1164,
+ n1165, n1166, n1167, n1168, n1169, n1170, n1171, n1172, n1173, n1174,
+ n1175, n1176, n1177, n1178, n1179, n1180, n1181, n1182, n1183, n1184,
+ n1185, n1186, n1187, n1188, n1189, n1190, n1191, n1192, n1193, n1194,
+ n1195, n1196, n1197, n1198, n1199, n1200, n1201, n1202, n1203, n1204,
+ n1205, n1206, n1207, n1208, n1209, n1210, n1211, n1212, n1213, n1214,
+ n1215, n1216, n1217, n1218, n1219, n1220, n1221, n1222, n1223, n1224,
+ n1225, n1226, n1227, n1228, n1229, n1230, n1231, n1232, n1233, n1234,
+ n1235, n1236, n1237, n1238, n1239, n1240, n1241, n1242, n1243, n1244,
+ n1245, n1246, n1247, n1248, n1249, n1250, n1251, n1252, n1253, n1254,
+ n1255, n1256, n1257, n1258, n1259, n1260, n1261, n1262, n1263, n1264,
+ n1265, n1266, n1267, n1268, n1269, n1270, n1271, n1272, n1273, n1274,
+ n1275, n1276, n1277, n1278, n1279, n1280, n1281, n1282, n1283, n1284,
+ n1285, n1286, n1287, n1288, n1289, n1290, n1291, n1292, n1293, n1294,
+ n1295, n1296, n1297, n1298, n1299, n1300, n1301, n1302, n1303, n1304,
+ n1305, n1306, n1307, n1308, n1309, n1310, n1311, n1312, n1313, n1314,
+ n1315, n1316, n1317, n1318, n1319, n1320, n1321, n1322, n1323, n1324,
+ n1325, n1326, n1327, n1328, n1329, n1330, n1331, n1332, n1333, n1334,
+ n1335, n1336, n1337, n1338, n1339, n1340, n1341, n1342, n1343, n1344,
+ n1345, n1346, n1347, n1348, n1349, n1350, n1351, n1352, n1353, n1354,
+ n1355, n1356, n1357, n1358, n1359, n1360, n1361, n1362, n1363, n1364,
+ n1365, n1366, n1367, n1368, n1369, n1370, n1371, n1372, n1373, n1374,
+ n1375, n1376, n1377, n1378, n1379, n1380, n1381, n1382, n1383, n1384,
+ n1385, n1386, n1387, n1388, n1389, n1390, n1391, n1392, n1393, n1394,
+ n1395, n1396;
+
+ AN2 U712 ( .A(n705), .B(po4), .Z(po7));
+ OR2 U713 ( .A(n706), .B(n707), .Z(n705));
+ AN2 U714 ( .A(n708), .B(n709), .Z(n707));
+ OR2 U715 ( .A(n710), .B(n711), .Z(n708));
+ AN2 U716 ( .A(n712), .B(n713), .Z(n711));
+ AN2 U717 ( .A(n714), .B(n715), .Z(n710));
+ AN2 U718 ( .A(n716), .B(n717), .Z(n714));
+ AN2 U719 ( .A(n718), .B(n719), .Z(n706));
+ OR2 U720 ( .A(n720), .B(n712), .Z(n719));
+ OR2 U721 ( .A(n721), .B(n722), .Z(n712));
+ AN2 U722 ( .A(n723), .B(n724), .Z(n722));
+ AN2 U723 ( .A(n725), .B(n726), .Z(n721));
+ OR2 U724 ( .A(n724), .B(n727), .Z(n726));
+ AN2 U725 ( .A(n727), .B(n723), .Z(n720));
+ OR2 U726 ( .A(n728), .B(n729), .Z(po6));
+ AN2 U727 ( .A(pi13), .B(n730), .Z(n729));
+ OR2 U728 ( .A(n731), .B(n732), .Z(n730));
+ OR2 U729 ( .A(n733), .B(n734), .Z(n732));
+ OR2 U730 ( .A(n735), .B(n736), .Z(n734));
+ AN2 U731 ( .A(n737), .B(n738), .Z(n736));
+ OR2 U732 ( .A(n739), .B(n740), .Z(n737));
+ OR2 U733 ( .A(n741), .B(n742), .Z(n740));
+ AN2 U734 ( .A(n743), .B(n744), .Z(n742));
+ OR2 U735 ( .A(n745), .B(n746), .Z(n743));
+ AN2 U736 ( .A(pi03), .B(n747), .Z(n745));
+ AN2 U737 ( .A(n748), .B(n749), .Z(n741));
+ AN2 U738 ( .A(n750), .B(n751), .Z(n748));
+ AN2 U739 ( .A(pi11), .B(n752), .Z(n735));
+ OR2 U740 ( .A(n753), .B(n754), .Z(n752));
+ OR2 U741 ( .A(n755), .B(n756), .Z(n754));
+ AN2 U742 ( .A(n757), .B(n747), .Z(n756));
+ OR2 U743 ( .A(n758), .B(n759), .Z(n757));
+ IV2 U744 ( .A(n760), .Z(n755));
+ AN2 U745 ( .A(n761), .B(n762), .Z(n753));
+ OR2 U746 ( .A(n763), .B(po5), .Z(n762));
+ AN2 U747 ( .A(n764), .B(n765), .Z(n763));
+ AN2 U748 ( .A(n766), .B(n767), .Z(n733));
+ OR2 U749 ( .A(n768), .B(n769), .Z(n767));
+ AN2 U750 ( .A(n770), .B(n771), .Z(n768));
+ IV2 U751 ( .A(n772), .Z(n766));
+ OR2 U752 ( .A(n773), .B(n774), .Z(n731));
+ AN2 U753 ( .A(n775), .B(n776), .Z(n774));
+ AN2 U754 ( .A(n777), .B(n778), .Z(n775));
+ AN2 U755 ( .A(n779), .B(n780), .Z(n773));
+ AN2 U756 ( .A(n781), .B(n782), .Z(n779));
+ AN2 U757 ( .A(n783), .B(n781), .Z(n728));
+ AN2 U758 ( .A(n782), .B(n784), .Z(n783));
+ OR2 U759 ( .A(n785), .B(n786), .Z(po3));
+ OR2 U760 ( .A(n787), .B(n788), .Z(n786));
+ OR2 U761 ( .A(n789), .B(n790), .Z(n788));
+ OR2 U762 ( .A(n791), .B(n792), .Z(n790));
+ AN2 U763 ( .A(n793), .B(n782), .Z(n792));
+ AN2 U764 ( .A(n794), .B(n795), .Z(n791));
+ OR2 U765 ( .A(n796), .B(n797), .Z(n789));
+ IV2 U766 ( .A(n798), .Z(n797));
+ OR2 U767 ( .A(n799), .B(n778), .Z(n798));
+ AN2 U768 ( .A(n778), .B(n799), .Z(n796));
+ OR2 U769 ( .A(n800), .B(n801), .Z(n799));
+ IV2 U770 ( .A(n802), .Z(n778));
+ OR2 U771 ( .A(n803), .B(n804), .Z(n802));
+ AN2 U772 ( .A(n805), .B(n806), .Z(n803));
+ AN2 U773 ( .A(n807), .B(n808), .Z(n806));
+ AN2 U774 ( .A(n809), .B(n810), .Z(n808));
+ OR2 U775 ( .A(pi11), .B(n811), .Z(n810));
+ AN2 U776 ( .A(n812), .B(n813), .Z(n811));
+ AN2 U777 ( .A(n814), .B(n815), .Z(n813));
+ OR2 U778 ( .A(n782), .B(n816), .Z(n815));
+ OR2 U779 ( .A(n817), .B(n818), .Z(n814));
+ OR2 U780 ( .A(n819), .B(n820), .Z(n818));
+ AN2 U781 ( .A(n750), .B(n821), .Z(n820));
+ AN2 U782 ( .A(n749), .B(n747), .Z(n819));
+ IV2 U783 ( .A(n821), .Z(n749));
+ AN2 U784 ( .A(n822), .B(n823), .Z(n812));
+ OR2 U785 ( .A(n824), .B(n825), .Z(n823));
+ OR2 U786 ( .A(n826), .B(n827), .Z(n822));
+ AN2 U787 ( .A(pi10), .B(n828), .Z(n826));
+ OR2 U788 ( .A(n829), .B(n830), .Z(n828));
+ OR2 U789 ( .A(n831), .B(n738), .Z(n809));
+ AN2 U790 ( .A(n832), .B(n833), .Z(n831));
+ AN2 U791 ( .A(n834), .B(n760), .Z(n833));
+ OR2 U792 ( .A(n817), .B(n835), .Z(n760));
+ OR2 U793 ( .A(pi03), .B(n836), .Z(n835));
+ OR2 U794 ( .A(n817), .B(n837), .Z(n834));
+ OR2 U795 ( .A(n715), .B(n827), .Z(n837));
+ IV2 U796 ( .A(n836), .Z(n715));
+ AN2 U797 ( .A(n838), .B(n839), .Z(n832));
+ OR2 U798 ( .A(n765), .B(n840), .Z(n839));
+ OR2 U799 ( .A(n841), .B(n825), .Z(n840));
+ OR2 U800 ( .A(n816), .B(n842), .Z(n838));
+ OR2 U801 ( .A(n843), .B(n844), .Z(n842));
+ AN2 U802 ( .A(n845), .B(n846), .Z(n844));
+ OR2 U803 ( .A(n847), .B(n848), .Z(n845));
+ AN2 U804 ( .A(n758), .B(n747), .Z(n848));
+ IV2 U805 ( .A(n849), .Z(n758));
+ AN2 U806 ( .A(n750), .B(n849), .Z(n847));
+ AN2 U807 ( .A(n849), .B(n759), .Z(n843));
+ OR2 U808 ( .A(n850), .B(n851), .Z(n849));
+ AN2 U809 ( .A(n852), .B(n853), .Z(n850));
+ IV2 U810 ( .A(n854), .Z(n816));
+ AN2 U811 ( .A(n855), .B(n856), .Z(n807));
+ OR2 U812 ( .A(n857), .B(n858), .Z(n856));
+ OR2 U813 ( .A(n859), .B(n860), .Z(n858));
+ AN2 U814 ( .A(n861), .B(n739), .Z(n859));
+ OR2 U815 ( .A(n862), .B(n863), .Z(n739));
+ AN2 U816 ( .A(n759), .B(n795), .Z(n862));
+ OR2 U817 ( .A(n846), .B(n864), .Z(n861));
+ IV2 U818 ( .A(n865), .Z(n864));
+ AN2 U819 ( .A(n795), .B(n863), .Z(n865));
+ IV2 U820 ( .A(n759), .Z(n846));
+ OR2 U821 ( .A(n866), .B(n867), .Z(n759));
+ AN2 U822 ( .A(n868), .B(po5), .Z(n867));
+ AN2 U823 ( .A(n750), .B(n869), .Z(n866));
+ OR2 U824 ( .A(n825), .B(n870), .Z(n855));
+ OR2 U825 ( .A(n871), .B(n872), .Z(n870));
+ AN2 U826 ( .A(n764), .B(n873), .Z(n872));
+ IV2 U827 ( .A(po5), .Z(n873));
+ AN2 U828 ( .A(n841), .B(po4), .Z(n871));
+ OR2 U829 ( .A(n874), .B(po5), .Z(po4));
+ IV2 U830 ( .A(n764), .Z(n841));
+ OR2 U831 ( .A(n875), .B(n724), .Z(n764));
+ AN2 U832 ( .A(n876), .B(n877), .Z(n875));
+ AN2 U833 ( .A(n878), .B(n879), .Z(n805));
+ AN2 U834 ( .A(n880), .B(n881), .Z(n879));
+ OR2 U835 ( .A(n782), .B(n882), .Z(n881));
+ OR2 U836 ( .A(n781), .B(n883), .Z(n882));
+ IV2 U837 ( .A(n884), .Z(n781));
+ OR2 U838 ( .A(n795), .B(n885), .Z(n880));
+ AN2 U839 ( .A(n886), .B(n887), .Z(n878));
+ OR2 U840 ( .A(pi03), .B(n888), .Z(n887));
+ AN2 U841 ( .A(n889), .B(n890), .Z(n888));
+ IV2 U842 ( .A(n891), .Z(n890));
+ AN2 U843 ( .A(n830), .B(n892), .Z(n891));
+ OR2 U844 ( .A(n893), .B(n894), .Z(n830));
+ IV2 U845 ( .A(n895), .Z(n894));
+ OR2 U846 ( .A(n746), .B(n750), .Z(n895));
+ AN2 U847 ( .A(n750), .B(n746), .Z(n893));
+ OR2 U848 ( .A(n896), .B(n897), .Z(n746));
+ AN2 U849 ( .A(pi02), .B(n898), .Z(n896));
+ IV2 U850 ( .A(n747), .Z(n750));
+ OR2 U851 ( .A(n899), .B(n900), .Z(n747));
+ AN2 U852 ( .A(n901), .B(n771), .Z(n900));
+ OR2 U853 ( .A(pi03), .B(n795), .Z(n771));
+ AN2 U854 ( .A(n902), .B(n903), .Z(n899));
+ OR2 U855 ( .A(n904), .B(n905), .Z(n903));
+ OR2 U856 ( .A(n906), .B(n907), .Z(n905));
+ AN2 U857 ( .A(n782), .B(n892), .Z(n907));
+ AN2 U858 ( .A(n769), .B(n751), .Z(n906));
+ AN2 U859 ( .A(po5), .B(n908), .Z(n904));
+ OR2 U860 ( .A(n909), .B(n772), .Z(n889));
+ AN2 U861 ( .A(n910), .B(n911), .Z(n909));
+ OR2 U862 ( .A(n912), .B(n795), .Z(n911));
+ OR2 U863 ( .A(n782), .B(n770), .Z(n910));
+ OR2 U864 ( .A(n827), .B(n913), .Z(n886));
+ OR2 U865 ( .A(n914), .B(n772), .Z(n913));
+ OR2 U866 ( .A(n915), .B(n916), .Z(n914));
+ AN2 U867 ( .A(n912), .B(n795), .Z(n916));
+ IV2 U868 ( .A(n770), .Z(n912));
+ AN2 U869 ( .A(n782), .B(n770), .Z(n915));
+ OR2 U870 ( .A(n917), .B(n918), .Z(n770));
+ AN2 U871 ( .A(n919), .B(n920), .Z(n917));
+ IV2 U872 ( .A(n795), .Z(n782));
+ OR2 U873 ( .A(n921), .B(n922), .Z(n787));
+ AN2 U874 ( .A(n923), .B(n824), .Z(n922));
+ AN2 U875 ( .A(n924), .B(n925), .Z(n923));
+ OR2 U876 ( .A(n926), .B(n927), .Z(n925));
+ AN2 U877 ( .A(pi11), .B(pi03), .Z(n926));
+ AN2 U878 ( .A(pi07), .B(n928), .Z(n921));
+ OR2 U879 ( .A(n929), .B(n930), .Z(n928));
+ AN2 U880 ( .A(n931), .B(n804), .Z(n929));
+ OR2 U881 ( .A(n932), .B(n933), .Z(n931));
+ AN2 U882 ( .A(n854), .B(n795), .Z(n933));
+ AN2 U883 ( .A(n934), .B(n827), .Z(n932));
+ OR2 U884 ( .A(n935), .B(n936), .Z(n785));
+ OR2 U885 ( .A(n937), .B(n938), .Z(n936));
+ AN2 U886 ( .A(n939), .B(n940), .Z(n938));
+ OR2 U887 ( .A(n941), .B(n942), .Z(n940));
+ OR2 U888 ( .A(n769), .B(n943), .Z(n942));
+ AN2 U889 ( .A(n874), .B(n944), .Z(n943));
+ AN2 U890 ( .A(n795), .B(pi03), .Z(n769));
+ OR2 U891 ( .A(n945), .B(n946), .Z(n795));
+ OR2 U892 ( .A(n947), .B(n948), .Z(n946));
+ AN2 U893 ( .A(n949), .B(n824), .Z(n948));
+ AN2 U894 ( .A(n950), .B(n765), .Z(n947));
+ IV2 U895 ( .A(n874), .Z(n765));
+ OR2 U896 ( .A(n951), .B(n952), .Z(n945));
+ OR2 U897 ( .A(n953), .B(n954), .Z(n952));
+ AN2 U898 ( .A(n955), .B(n827), .Z(n954));
+ OR2 U899 ( .A(n956), .B(n957), .Z(n955));
+ AN2 U900 ( .A(n958), .B(n784), .Z(n956));
+ AN2 U901 ( .A(pi07), .B(n959), .Z(n958));
+ AN2 U902 ( .A(po5), .B(n960), .Z(n953));
+ OR2 U903 ( .A(n961), .B(n962), .Z(n960));
+ AN2 U904 ( .A(n892), .B(n963), .Z(n962));
+ AN2 U905 ( .A(n964), .B(n965), .Z(n961));
+ AN2 U906 ( .A(pi13), .B(n966), .Z(n951));
+ OR2 U907 ( .A(n967), .B(n968), .Z(n966));
+ OR2 U908 ( .A(n969), .B(n970), .Z(n968));
+ AN2 U909 ( .A(n971), .B(pi02), .Z(n970));
+ AN2 U910 ( .A(n972), .B(n973), .Z(n969));
+ AN2 U911 ( .A(n974), .B(n975), .Z(n972));
+ OR2 U912 ( .A(n874), .B(n959), .Z(n975));
+ AN2 U913 ( .A(n827), .B(n824), .Z(n874));
+ IV2 U914 ( .A(pi03), .Z(n827));
+ OR2 U915 ( .A(n964), .B(n976), .Z(n974));
+ AN2 U916 ( .A(pi03), .B(n824), .Z(n976));
+ IV2 U917 ( .A(pi07), .Z(n824));
+ IV2 U918 ( .A(n959), .Z(n964));
+ OR2 U919 ( .A(n977), .B(n978), .Z(n959));
+ AN2 U920 ( .A(n979), .B(pi02), .Z(n978));
+ AN2 U921 ( .A(n980), .B(n717), .Z(n977));
+ OR2 U922 ( .A(n979), .B(pi02), .Z(n980));
+ AN2 U923 ( .A(n981), .B(po5), .Z(n967));
+ AN2 U924 ( .A(po5), .B(n982), .Z(n941));
+ AN2 U925 ( .A(pi03), .B(pi07), .Z(po5));
+ AN2 U926 ( .A(n983), .B(pi03), .Z(n935));
+ OR2 U927 ( .A(n984), .B(n985), .Z(po2));
+ OR2 U928 ( .A(n986), .B(n987), .Z(n985));
+ OR2 U929 ( .A(n988), .B(n989), .Z(n987));
+ OR2 U930 ( .A(n990), .B(n991), .Z(n989));
+ AN2 U931 ( .A(n793), .B(n992), .Z(n991));
+ AN2 U932 ( .A(n794), .B(n993), .Z(n990));
+ OR2 U933 ( .A(n994), .B(n995), .Z(n988));
+ AN2 U934 ( .A(n777), .B(n801), .Z(n995));
+ IV2 U935 ( .A(n800), .Z(n777));
+ AN2 U936 ( .A(n776), .B(n800), .Z(n994));
+ OR2 U937 ( .A(n996), .B(n804), .Z(n800));
+ AN2 U938 ( .A(n997), .B(n998), .Z(n996));
+ AN2 U939 ( .A(n999), .B(n1000), .Z(n998));
+ AN2 U940 ( .A(n1001), .B(n1002), .Z(n1000));
+ OR2 U941 ( .A(n1003), .B(n817), .Z(n1002));
+ AN2 U942 ( .A(n1004), .B(n836), .Z(n1003));
+ OR2 U943 ( .A(pi00), .B(n1005), .Z(n836));
+ OR2 U944 ( .A(pi02), .B(pi01), .Z(n1005));
+ AN2 U945 ( .A(n1006), .B(n1007), .Z(n1004));
+ OR2 U946 ( .A(pi11), .B(n1008), .Z(n1007));
+ AN2 U947 ( .A(n1009), .B(n821), .Z(n1008));
+ OR2 U948 ( .A(n898), .B(n1010), .Z(n821));
+ OR2 U949 ( .A(n1011), .B(n851), .Z(n1009));
+ AN2 U950 ( .A(n1012), .B(n1013), .Z(n1011));
+ OR2 U951 ( .A(n738), .B(n1014), .Z(n1006));
+ OR2 U952 ( .A(n1015), .B(n1016), .Z(n1014));
+ AN2 U953 ( .A(n713), .B(n1017), .Z(n1015));
+ OR2 U954 ( .A(n1018), .B(n1019), .Z(n1001));
+ OR2 U955 ( .A(n744), .B(n1020), .Z(n1019));
+ OR2 U956 ( .A(n1021), .B(n1022), .Z(n1018));
+ AN2 U957 ( .A(n717), .B(n1023), .Z(n1022));
+ AN2 U958 ( .A(n863), .B(n1024), .Z(n1021));
+ OR2 U959 ( .A(n1025), .B(n1026), .Z(n1024));
+ OR2 U960 ( .A(n992), .B(n852), .Z(n1026));
+ IV2 U961 ( .A(n1027), .Z(n1025));
+ OR2 U962 ( .A(n1028), .B(n1027), .Z(n863));
+ OR2 U963 ( .A(n1029), .B(n1030), .Z(n1027));
+ AN2 U964 ( .A(n1031), .B(n1032), .Z(n1029));
+ AN2 U965 ( .A(n1033), .B(n993), .Z(n1028));
+ AN2 U966 ( .A(n885), .B(n1034), .Z(n999));
+ OR2 U967 ( .A(n825), .B(n1035), .Z(n1034));
+ OR2 U968 ( .A(n1036), .B(n1037), .Z(n1035));
+ AN2 U969 ( .A(n1038), .B(n1039), .Z(n1037));
+ IV2 U970 ( .A(n724), .Z(n1039));
+ OR2 U971 ( .A(n877), .B(n738), .Z(n1038));
+ IV2 U972 ( .A(n876), .Z(n1036));
+ OR2 U973 ( .A(n1040), .B(n884), .Z(n885));
+ OR2 U974 ( .A(n1041), .B(n1042), .Z(n884));
+ OR2 U975 ( .A(n993), .B(n1032), .Z(n1042));
+ AN2 U976 ( .A(n1043), .B(n1044), .Z(n997));
+ AN2 U977 ( .A(n1045), .B(n1046), .Z(n1044));
+ OR2 U978 ( .A(pi02), .B(n1047), .Z(n1046));
+ AN2 U979 ( .A(n1048), .B(n1049), .Z(n1047));
+ OR2 U980 ( .A(n876), .B(n1050), .Z(n1049));
+ OR2 U981 ( .A(n717), .B(n825), .Z(n1050));
+ AN2 U982 ( .A(n1051), .B(n1052), .Z(n1048));
+ OR2 U983 ( .A(n1053), .B(n1054), .Z(n1052));
+ OR2 U984 ( .A(n1055), .B(n772), .Z(n1051));
+ AN2 U985 ( .A(n1056), .B(n1057), .Z(n1055));
+ OR2 U986 ( .A(n1058), .B(n993), .Z(n1057));
+ OR2 U987 ( .A(n992), .B(n919), .Z(n1056));
+ OR2 U988 ( .A(n1059), .B(n1016), .Z(n1045));
+ AN2 U989 ( .A(n1060), .B(n1061), .Z(n1059));
+ AN2 U990 ( .A(n1062), .B(n1063), .Z(n1061));
+ OR2 U991 ( .A(n876), .B(n1064), .Z(n1062));
+ OR2 U992 ( .A(pi06), .B(n825), .Z(n1064));
+ OR2 U993 ( .A(n1065), .B(n725), .Z(n876));
+ AN2 U994 ( .A(n718), .B(n1066), .Z(n1065));
+ AN2 U995 ( .A(n1067), .B(n1068), .Z(n1060));
+ OR2 U996 ( .A(n772), .B(n1069), .Z(n1068));
+ OR2 U997 ( .A(n1070), .B(n1071), .Z(n1069));
+ AN2 U998 ( .A(n1058), .B(n993), .Z(n1071));
+ IV2 U999 ( .A(n919), .Z(n1058));
+ AN2 U1000 ( .A(n992), .B(n919), .Z(n1070));
+ OR2 U1001 ( .A(n1072), .B(n1073), .Z(n919));
+ AN2 U1002 ( .A(n1074), .B(n1075), .Z(n1072));
+ OR2 U1003 ( .A(n1054), .B(n1076), .Z(n1067));
+ IV2 U1004 ( .A(n1053), .Z(n1076));
+ AN2 U1005 ( .A(n1077), .B(n1078), .Z(n1053));
+ OR2 U1006 ( .A(n897), .B(n851), .Z(n1078));
+ IV2 U1007 ( .A(n1079), .Z(n1077));
+ AN2 U1008 ( .A(n851), .B(n897), .Z(n1079));
+ OR2 U1009 ( .A(n1080), .B(n1081), .Z(n897));
+ AN2 U1010 ( .A(pi01), .B(n1082), .Z(n1080));
+ AN2 U1011 ( .A(n1083), .B(n1084), .Z(n1043));
+ OR2 U1012 ( .A(pi10), .B(n1085), .Z(n1084));
+ OR2 U1013 ( .A(n1086), .B(n1087), .Z(n1085));
+ AN2 U1014 ( .A(n1088), .B(n1089), .Z(n1087));
+ AN2 U1015 ( .A(n852), .B(n898), .Z(n1088));
+ IV2 U1016 ( .A(n1033), .Z(n852));
+ AN2 U1017 ( .A(n1090), .B(n853), .Z(n1086));
+ IV2 U1018 ( .A(n1089), .Z(n853));
+ AN2 U1019 ( .A(n1091), .B(n1082), .Z(n1089));
+ OR2 U1020 ( .A(n1031), .B(n1092), .Z(n1091));
+ OR2 U1021 ( .A(n851), .B(n1033), .Z(n1090));
+ OR2 U1022 ( .A(n1093), .B(n1094), .Z(n1033));
+ AN2 U1023 ( .A(n868), .B(n724), .Z(n1094));
+ AN2 U1024 ( .A(n851), .B(n869), .Z(n1093));
+ IV2 U1025 ( .A(n898), .Z(n851));
+ OR2 U1026 ( .A(n1095), .B(n1096), .Z(n898));
+ AN2 U1027 ( .A(n901), .B(n920), .Z(n1096));
+ OR2 U1028 ( .A(pi02), .B(n993), .Z(n920));
+ AN2 U1029 ( .A(n902), .B(n1097), .Z(n1095));
+ OR2 U1030 ( .A(n1098), .B(n1099), .Z(n1097));
+ OR2 U1031 ( .A(n1100), .B(n1101), .Z(n1099));
+ AN2 U1032 ( .A(n992), .B(n892), .Z(n1101));
+ AN2 U1033 ( .A(n918), .B(n751), .Z(n1100));
+ AN2 U1034 ( .A(n908), .B(n724), .Z(n1098));
+ OR2 U1035 ( .A(n1102), .B(n992), .Z(n1083));
+ IV2 U1036 ( .A(n993), .Z(n992));
+ AN2 U1037 ( .A(n1103), .B(n1104), .Z(n1102));
+ OR2 U1038 ( .A(n883), .B(n1105), .Z(n1104));
+ IV2 U1039 ( .A(n1106), .Z(n883));
+ IV2 U1040 ( .A(n801), .Z(n776));
+ OR2 U1041 ( .A(n1107), .B(n1108), .Z(n801));
+ OR2 U1042 ( .A(pi12), .B(n1109), .Z(n1108));
+ OR2 U1043 ( .A(n1110), .B(n1111), .Z(n986));
+ AN2 U1044 ( .A(n1112), .B(n717), .Z(n1111));
+ AN2 U1045 ( .A(n924), .B(n1113), .Z(n1112));
+ OR2 U1046 ( .A(n1114), .B(n927), .Z(n1113));
+ AN2 U1047 ( .A(pi11), .B(pi02), .Z(n1114));
+ AN2 U1048 ( .A(pi06), .B(n1115), .Z(n1110));
+ OR2 U1049 ( .A(n1116), .B(n930), .Z(n1115));
+ AN2 U1050 ( .A(n1117), .B(n804), .Z(n1116));
+ OR2 U1051 ( .A(n1118), .B(n1119), .Z(n1117));
+ AN2 U1052 ( .A(n854), .B(n993), .Z(n1119));
+ AN2 U1053 ( .A(n934), .B(n1016), .Z(n1118));
+ OR2 U1054 ( .A(n1120), .B(n1121), .Z(n984));
+ OR2 U1055 ( .A(n937), .B(n1122), .Z(n1121));
+ AN2 U1056 ( .A(n939), .B(n1123), .Z(n1122));
+ OR2 U1057 ( .A(n1124), .B(n1125), .Z(n1123));
+ OR2 U1058 ( .A(n918), .B(n1126), .Z(n1125));
+ AN2 U1059 ( .A(n724), .B(n982), .Z(n1126));
+ AN2 U1060 ( .A(n993), .B(pi02), .Z(n918));
+ OR2 U1061 ( .A(n1127), .B(n1128), .Z(n993));
+ OR2 U1062 ( .A(n1129), .B(n1130), .Z(n1128));
+ AN2 U1063 ( .A(n949), .B(n717), .Z(n1130));
+ AN2 U1064 ( .A(n950), .B(n877), .Z(n1129));
+ IV2 U1065 ( .A(n727), .Z(n877));
+ OR2 U1066 ( .A(n1131), .B(n1132), .Z(n1127));
+ OR2 U1067 ( .A(n1133), .B(n1134), .Z(n1132));
+ AN2 U1068 ( .A(n1135), .B(n1016), .Z(n1134));
+ OR2 U1069 ( .A(n1136), .B(n957), .Z(n1135));
+ AN2 U1070 ( .A(n1137), .B(n979), .Z(n1136));
+ AN2 U1071 ( .A(n784), .B(pi06), .Z(n1137));
+ AN2 U1072 ( .A(n724), .B(n1138), .Z(n1133));
+ OR2 U1073 ( .A(n1139), .B(n1140), .Z(n1138));
+ AN2 U1074 ( .A(n965), .B(n1141), .Z(n1139));
+ AN2 U1075 ( .A(pi02), .B(pi06), .Z(n724));
+ AN2 U1076 ( .A(pi13), .B(n1142), .Z(n1131));
+ OR2 U1077 ( .A(n1143), .B(n1144), .Z(n1142));
+ AN2 U1078 ( .A(n971), .B(pi01), .Z(n1144));
+ AN2 U1079 ( .A(n1145), .B(n973), .Z(n1143));
+ AN2 U1080 ( .A(n1146), .B(n1147), .Z(n1145));
+ OR2 U1081 ( .A(n727), .B(n979), .Z(n1147));
+ IV2 U1082 ( .A(n1141), .Z(n979));
+ OR2 U1083 ( .A(n1148), .B(n1141), .Z(n1146));
+ OR2 U1084 ( .A(n1149), .B(n1150), .Z(n1141));
+ AN2 U1085 ( .A(n1151), .B(n1017), .Z(n1150));
+ AN2 U1086 ( .A(pi05), .B(n1152), .Z(n1149));
+ OR2 U1087 ( .A(n1151), .B(n1017), .Z(n1152));
+ AN2 U1088 ( .A(pi02), .B(n717), .Z(n1148));
+ AN2 U1089 ( .A(n944), .B(n727), .Z(n1124));
+ AN2 U1090 ( .A(n1016), .B(n717), .Z(n727));
+ IV2 U1091 ( .A(pi06), .Z(n717));
+ IV2 U1092 ( .A(pi02), .Z(n1016));
+ AN2 U1093 ( .A(n983), .B(pi02), .Z(n1120));
+ OR2 U1094 ( .A(n1153), .B(n1154), .Z(po1));
+ OR2 U1095 ( .A(n1155), .B(n1156), .Z(n1154));
+ OR2 U1096 ( .A(n1157), .B(n1158), .Z(n1156));
+ OR2 U1097 ( .A(n1159), .B(n1160), .Z(n1158));
+ AN2 U1098 ( .A(n793), .B(n1105), .Z(n1160));
+ AN2 U1099 ( .A(n794), .B(n1032), .Z(n1159));
+ OR2 U1100 ( .A(n1161), .B(n1162), .Z(n1157));
+ AN2 U1101 ( .A(n1163), .B(n1107), .Z(n1162));
+ IV2 U1102 ( .A(n1164), .Z(n1161));
+ OR2 U1103 ( .A(n1107), .B(n1163), .Z(n1164));
+ AN2 U1104 ( .A(n1165), .B(n1166), .Z(n1163));
+ OR2 U1105 ( .A(n1167), .B(n804), .Z(n1107));
+ AN2 U1106 ( .A(n1168), .B(n1169), .Z(n1167));
+ AN2 U1107 ( .A(n1170), .B(n1171), .Z(n1169));
+ OR2 U1108 ( .A(n817), .B(n1172), .Z(n1171));
+ OR2 U1109 ( .A(pi11), .B(n1173), .Z(n1172));
+ AN2 U1110 ( .A(n1010), .B(n1174), .Z(n1173));
+ OR2 U1111 ( .A(n1012), .B(n1013), .Z(n1174));
+ OR2 U1112 ( .A(n1175), .B(n1082), .Z(n1010));
+ AN2 U1113 ( .A(n1176), .B(n1177), .Z(n1170));
+ OR2 U1114 ( .A(pi10), .B(n1178), .Z(n1177));
+ OR2 U1115 ( .A(n1179), .B(n1180), .Z(n1178));
+ AN2 U1116 ( .A(n1181), .B(n1031), .Z(n1180));
+ IV2 U1117 ( .A(n1182), .Z(n1179));
+ OR2 U1118 ( .A(n1181), .B(n1031), .Z(n1182));
+ OR2 U1119 ( .A(n1183), .B(n1184), .Z(n1181));
+ AN2 U1120 ( .A(n1185), .B(n1082), .Z(n1184));
+ AN2 U1121 ( .A(n1012), .B(n1092), .Z(n1183));
+ OR2 U1122 ( .A(n825), .B(n1186), .Z(n1176));
+ OR2 U1123 ( .A(n1187), .B(n1188), .Z(n1186));
+ AN2 U1124 ( .A(n1189), .B(n1190), .Z(n1187));
+ IV2 U1125 ( .A(n725), .Z(n1190));
+ OR2 U1126 ( .A(n1066), .B(n738), .Z(n1189));
+ AN2 U1127 ( .A(n1191), .B(n1192), .Z(n1168));
+ AN2 U1128 ( .A(n1193), .B(n1194), .Z(n1192));
+ OR2 U1129 ( .A(n1195), .B(n1017), .Z(n1194));
+ AN2 U1130 ( .A(n1196), .B(n1197), .Z(n1195));
+ AN2 U1131 ( .A(n1198), .B(n1199), .Z(n1197));
+ OR2 U1132 ( .A(pi05), .B(n1200), .Z(n1199));
+ AN2 U1133 ( .A(n1201), .B(n1063), .Z(n1198));
+ OR2 U1134 ( .A(n1202), .B(n772), .Z(n1201));
+ AN2 U1135 ( .A(n1203), .B(n1204), .Z(n1202));
+ OR2 U1136 ( .A(n1074), .B(n1032), .Z(n1204));
+ OR2 U1137 ( .A(n1105), .B(n1205), .Z(n1203));
+ AN2 U1138 ( .A(n1206), .B(n1207), .Z(n1196));
+ OR2 U1139 ( .A(n1208), .B(n1054), .Z(n1207));
+ AN2 U1140 ( .A(n1209), .B(n1210), .Z(n1208));
+ OR2 U1141 ( .A(n1081), .B(n1082), .Z(n1210));
+ OR2 U1142 ( .A(n1012), .B(n1211), .Z(n1209));
+ IV2 U1143 ( .A(n1081), .Z(n1211));
+ OR2 U1144 ( .A(n817), .B(n1212), .Z(n1206));
+ OR2 U1145 ( .A(n713), .B(n738), .Z(n1212));
+ OR2 U1146 ( .A(pi01), .B(n1213), .Z(n1193));
+ AN2 U1147 ( .A(n1214), .B(n1215), .Z(n1213));
+ AN2 U1148 ( .A(n1216), .B(n1217), .Z(n1215));
+ OR2 U1149 ( .A(n1054), .B(n1218), .Z(n1216));
+ OR2 U1150 ( .A(n1012), .B(n1081), .Z(n1218));
+ AN2 U1151 ( .A(pi00), .B(n1175), .Z(n1081));
+ OR2 U1152 ( .A(pi08), .B(n1020), .Z(n1054));
+ AN2 U1153 ( .A(n1219), .B(n1220), .Z(n1214));
+ OR2 U1154 ( .A(n772), .B(n1221), .Z(n1220));
+ OR2 U1155 ( .A(n1222), .B(n1223), .Z(n1221));
+ AN2 U1156 ( .A(n1074), .B(n1032), .Z(n1223));
+ AN2 U1157 ( .A(n1105), .B(n1205), .Z(n1222));
+ OR2 U1158 ( .A(n1224), .B(n738), .Z(n772));
+ AN2 U1159 ( .A(n1225), .B(n829), .Z(n1224));
+ OR2 U1160 ( .A(n751), .B(n1023), .Z(n1225));
+ OR2 U1161 ( .A(n716), .B(n1200), .Z(n1219));
+ OR2 U1162 ( .A(n718), .B(n825), .Z(n1200));
+ IV2 U1163 ( .A(n761), .Z(n825));
+ AN2 U1164 ( .A(n1226), .B(n1227), .Z(n1191));
+ OR2 U1165 ( .A(n1228), .B(n1229), .Z(n1227));
+ OR2 U1166 ( .A(n1020), .B(n1230), .Z(n1229));
+ OR2 U1167 ( .A(n1231), .B(n1232), .Z(n1230));
+ AN2 U1168 ( .A(n1233), .B(n1234), .Z(n1232));
+ AN2 U1169 ( .A(n1235), .B(n1031), .Z(n1233));
+ OR2 U1170 ( .A(n1030), .B(n1032), .Z(n1235));
+ AN2 U1171 ( .A(n1092), .B(n1041), .Z(n1030));
+ IV2 U1172 ( .A(n1236), .Z(n1231));
+ OR2 U1173 ( .A(n1234), .B(n1031), .Z(n1236));
+ OR2 U1174 ( .A(n1237), .B(n1238), .Z(n1031));
+ AN2 U1175 ( .A(n868), .B(n725), .Z(n1238));
+ AN2 U1176 ( .A(n1012), .B(n869), .Z(n1237));
+ IV2 U1177 ( .A(n1082), .Z(n1012));
+ OR2 U1178 ( .A(n1239), .B(n1240), .Z(n1082));
+ AN2 U1179 ( .A(n901), .B(n1075), .Z(n1240));
+ OR2 U1180 ( .A(pi01), .B(n1032), .Z(n1075));
+ AN2 U1181 ( .A(n902), .B(n1241), .Z(n1239));
+ OR2 U1182 ( .A(n1242), .B(n1243), .Z(n1241));
+ OR2 U1183 ( .A(n1244), .B(n1245), .Z(n1243));
+ AN2 U1184 ( .A(n1105), .B(n892), .Z(n1245));
+ AN2 U1185 ( .A(n1073), .B(n751), .Z(n1244));
+ AN2 U1186 ( .A(n908), .B(n725), .Z(n1242));
+ OR2 U1187 ( .A(n1185), .B(n1246), .Z(n1234));
+ OR2 U1188 ( .A(n1247), .B(n1105), .Z(n1246));
+ IV2 U1189 ( .A(n1248), .Z(n1020));
+ OR2 U1190 ( .A(n1249), .B(n744), .Z(n1228));
+ AN2 U1191 ( .A(n716), .B(n1023), .Z(n1249));
+ AN2 U1192 ( .A(n1250), .B(n1251), .Z(n1226));
+ OR2 U1193 ( .A(n1105), .B(n1103), .Z(n1251));
+ IV2 U1194 ( .A(n1252), .Z(n1103));
+ OR2 U1195 ( .A(n1253), .B(n1254), .Z(n1252));
+ AN2 U1196 ( .A(n1106), .B(n1041), .Z(n1254));
+ OR2 U1197 ( .A(n1255), .B(n780), .Z(n1106));
+ AN2 U1198 ( .A(n973), .B(n738), .Z(n1255));
+ AN2 U1199 ( .A(n854), .B(n738), .Z(n1253));
+ IV2 U1200 ( .A(n1032), .Z(n1105));
+ OR2 U1201 ( .A(n1032), .B(n1256), .Z(n1250));
+ OR2 U1202 ( .A(n1040), .B(n1041), .Z(n1256));
+ IV2 U1203 ( .A(n1257), .Z(n1040));
+ OR2 U1204 ( .A(n1258), .B(n1259), .Z(n1155));
+ AN2 U1205 ( .A(n1260), .B(n716), .Z(n1259));
+ AN2 U1206 ( .A(n924), .B(n1261), .Z(n1260));
+ OR2 U1207 ( .A(n1262), .B(n927), .Z(n1261));
+ AN2 U1208 ( .A(pi11), .B(pi01), .Z(n1262));
+ AN2 U1209 ( .A(pi05), .B(n1263), .Z(n1258));
+ OR2 U1210 ( .A(n1264), .B(n930), .Z(n1263));
+ AN2 U1211 ( .A(n1265), .B(n804), .Z(n1264));
+ OR2 U1212 ( .A(n1266), .B(n1267), .Z(n1265));
+ AN2 U1213 ( .A(n854), .B(n1032), .Z(n1267));
+ AN2 U1214 ( .A(n934), .B(n1017), .Z(n1266));
+ AN2 U1215 ( .A(pi11), .B(n761), .Z(n934));
+ OR2 U1216 ( .A(n1268), .B(n1269), .Z(n1153));
+ OR2 U1217 ( .A(n937), .B(n1270), .Z(n1269));
+ AN2 U1218 ( .A(n939), .B(n1271), .Z(n1270));
+ OR2 U1219 ( .A(n1272), .B(n1273), .Z(n1271));
+ OR2 U1220 ( .A(n1073), .B(n1274), .Z(n1273));
+ AN2 U1221 ( .A(n725), .B(n982), .Z(n1274));
+ AN2 U1222 ( .A(n1032), .B(pi01), .Z(n1073));
+ OR2 U1223 ( .A(n1275), .B(n1276), .Z(n1032));
+ OR2 U1224 ( .A(n1277), .B(n1278), .Z(n1276));
+ AN2 U1225 ( .A(n949), .B(n716), .Z(n1278));
+ AN2 U1226 ( .A(n950), .B(n1066), .Z(n1277));
+ IV2 U1227 ( .A(n723), .Z(n1066));
+ OR2 U1228 ( .A(n1279), .B(n1280), .Z(n1275));
+ OR2 U1229 ( .A(n1281), .B(n1282), .Z(n1280));
+ AN2 U1230 ( .A(n1283), .B(n1017), .Z(n1282));
+ OR2 U1231 ( .A(n1284), .B(n957), .Z(n1283));
+ AN2 U1232 ( .A(n1285), .B(n784), .Z(n1284));
+ AN2 U1233 ( .A(pi05), .B(n1286), .Z(n1285));
+ AN2 U1234 ( .A(n725), .B(n1287), .Z(n1281));
+ OR2 U1235 ( .A(n1288), .B(n1140), .Z(n1287));
+ AN2 U1236 ( .A(n965), .B(n1151), .Z(n1288));
+ AN2 U1237 ( .A(n744), .B(n902), .Z(n965));
+ AN2 U1238 ( .A(pi01), .B(pi05), .Z(n725));
+ AN2 U1239 ( .A(pi13), .B(n1289), .Z(n1279));
+ OR2 U1240 ( .A(n1290), .B(n1291), .Z(n1289));
+ AN2 U1241 ( .A(n971), .B(pi00), .Z(n1291));
+ AN2 U1242 ( .A(n892), .B(n1292), .Z(n971));
+ AN2 U1243 ( .A(pi10), .B(pi11), .Z(n1292));
+ AN2 U1244 ( .A(n1293), .B(n973), .Z(n1290));
+ AN2 U1245 ( .A(n1294), .B(n1295), .Z(n1293));
+ OR2 U1246 ( .A(n723), .B(n1286), .Z(n1295));
+ IV2 U1247 ( .A(n1151), .Z(n1286));
+ OR2 U1248 ( .A(n1151), .B(n1296), .Z(n1294));
+ AN2 U1249 ( .A(pi01), .B(n716), .Z(n1296));
+ AN2 U1250 ( .A(n944), .B(n723), .Z(n1272));
+ AN2 U1251 ( .A(n1017), .B(n716), .Z(n723));
+ IV2 U1252 ( .A(pi05), .Z(n716));
+ IV2 U1253 ( .A(pi01), .Z(n1017));
+ AN2 U1254 ( .A(n983), .B(pi01), .Z(n1268));
+ AN2 U1255 ( .A(pi11), .B(n1297), .Z(n983));
+ OR2 U1256 ( .A(n1298), .B(n1299), .Z(po0));
+ OR2 U1257 ( .A(n1300), .B(n1301), .Z(n1299));
+ OR2 U1258 ( .A(n1302), .B(n1303), .Z(n1301));
+ OR2 U1259 ( .A(n1304), .B(n1305), .Z(n1303));
+ AN2 U1260 ( .A(n793), .B(n1247), .Z(n1305));
+ AN2 U1261 ( .A(n924), .B(n1306), .Z(n793));
+ IV2 U1262 ( .A(n1307), .Z(n1306));
+ OR2 U1263 ( .A(n854), .B(n1308), .Z(n1307));
+ AN2 U1264 ( .A(pi08), .B(n1063), .Z(n1308));
+ IV2 U1265 ( .A(n1309), .Z(n1063));
+ AN2 U1266 ( .A(n794), .B(n1041), .Z(n1304));
+ AN2 U1267 ( .A(n1310), .B(n924), .Z(n794));
+ OR2 U1268 ( .A(pi11), .B(n854), .Z(n1310));
+ AN2 U1269 ( .A(pi11), .B(n1311), .Z(n1302));
+ OR2 U1270 ( .A(n1312), .B(n1313), .Z(n1311));
+ OR2 U1271 ( .A(n1314), .B(n1315), .Z(n1313));
+ AN2 U1272 ( .A(n924), .B(n1316), .Z(n1315));
+ AN2 U1273 ( .A(n1317), .B(n761), .Z(n1314));
+ AN2 U1274 ( .A(n1023), .B(n908), .Z(n761));
+ AN2 U1275 ( .A(n1151), .B(n804), .Z(n1317));
+ AN2 U1276 ( .A(n1297), .B(pi00), .Z(n1312));
+ AN2 U1277 ( .A(n804), .B(n1318), .Z(n1297));
+ OR2 U1278 ( .A(pi10), .B(n892), .Z(n1318));
+ OR2 U1279 ( .A(n1319), .B(n1320), .Z(n1300));
+ AN2 U1280 ( .A(n1321), .B(n709), .Z(n1320));
+ AN2 U1281 ( .A(n927), .B(n924), .Z(n1321));
+ AN2 U1282 ( .A(pi04), .B(n1322), .Z(n1319));
+ OR2 U1283 ( .A(n1323), .B(n930), .Z(n1322));
+ AN2 U1284 ( .A(n939), .B(n1324), .Z(n930));
+ AN2 U1285 ( .A(n744), .B(pi11), .Z(n1324));
+ AN2 U1286 ( .A(n957), .B(n1041), .Z(n1323));
+ OR2 U1287 ( .A(n1325), .B(n1326), .Z(n1298));
+ OR2 U1288 ( .A(n937), .B(n1327), .Z(n1326));
+ AN2 U1289 ( .A(pi13), .B(n1328), .Z(n1327));
+ OR2 U1290 ( .A(n1329), .B(n1330), .Z(n1328));
+ AN2 U1291 ( .A(n1109), .B(n1166), .Z(n1330));
+ IV2 U1292 ( .A(pi12), .Z(n1166));
+ IV2 U1293 ( .A(n1165), .Z(n1109));
+ AN2 U1294 ( .A(pi12), .B(n1165), .Z(n1329));
+ OR2 U1295 ( .A(n1331), .B(n1332), .Z(n1165));
+ AN2 U1296 ( .A(pi13), .B(n1333), .Z(n1332));
+ OR2 U1297 ( .A(n1334), .B(n1335), .Z(n1333));
+ OR2 U1298 ( .A(n1336), .B(n1337), .Z(n1335));
+ AN2 U1299 ( .A(n1247), .B(n1257), .Z(n1337));
+ OR2 U1300 ( .A(n1338), .B(n780), .Z(n1257));
+ AN2 U1301 ( .A(n1023), .B(n751), .Z(n780));
+ AN2 U1302 ( .A(n944), .B(pi09), .Z(n1338));
+ AN2 U1303 ( .A(pi11), .B(n1339), .Z(n1336));
+ OR2 U1304 ( .A(n1340), .B(n1341), .Z(n1339));
+ OR2 U1305 ( .A(n1342), .B(n1343), .Z(n1341));
+ AN2 U1306 ( .A(n1344), .B(pi00), .Z(n1343));
+ AN2 U1307 ( .A(n1345), .B(n1247), .Z(n1344));
+ AN2 U1308 ( .A(pi10), .B(n1346), .Z(n1345));
+ AN2 U1309 ( .A(n1041), .B(n713), .Z(n1342));
+ IV2 U1310 ( .A(n1217), .Z(n1340));
+ OR2 U1311 ( .A(pi00), .B(n817), .Z(n1217));
+ OR2 U1312 ( .A(n1023), .B(n1346), .Z(n817));
+ OR2 U1313 ( .A(n1347), .B(n1348), .Z(n1334));
+ OR2 U1314 ( .A(n1349), .B(n1350), .Z(n1348));
+ AN2 U1315 ( .A(n1316), .B(n1023), .Z(n1350));
+ AN2 U1316 ( .A(n854), .B(n1351), .Z(n1349));
+ OR2 U1317 ( .A(n1352), .B(n1353), .Z(n1351));
+ AN2 U1318 ( .A(pi00), .B(n738), .Z(n1353));
+ AN2 U1319 ( .A(pi09), .B(n1041), .Z(n1352));
+ AN2 U1320 ( .A(n1248), .B(n1354), .Z(n1347));
+ OR2 U1321 ( .A(n1355), .B(n1356), .Z(n1354));
+ OR2 U1322 ( .A(n1357), .B(n1358), .Z(n1356));
+ AN2 U1323 ( .A(n1185), .B(n1041), .Z(n1358));
+ IV2 U1324 ( .A(n1092), .Z(n1185));
+ AN2 U1325 ( .A(n1247), .B(n1092), .Z(n1357));
+ OR2 U1326 ( .A(n1359), .B(n1360), .Z(n1092));
+ AN2 U1327 ( .A(n868), .B(n718), .Z(n1360));
+ AN2 U1328 ( .A(n1023), .B(n901), .Z(n868));
+ AN2 U1329 ( .A(n973), .B(pi11), .Z(n901));
+ AN2 U1330 ( .A(n869), .B(n1013), .Z(n1359));
+ AN2 U1331 ( .A(n1361), .B(n927), .Z(n869));
+ AN2 U1332 ( .A(n963), .B(pi08), .Z(n927));
+ IV2 U1333 ( .A(n1041), .Z(n1247));
+ AN2 U1334 ( .A(n1175), .B(n713), .Z(n1355));
+ IV2 U1335 ( .A(n1013), .Z(n1175));
+ AN2 U1336 ( .A(n1361), .B(n738), .Z(n1248));
+ AN2 U1337 ( .A(n1362), .B(n751), .Z(n1331));
+ AN2 U1338 ( .A(n902), .B(n1013), .Z(n1362));
+ OR2 U1339 ( .A(n1363), .B(n1364), .Z(n1013));
+ IV2 U1340 ( .A(n902), .Z(n1364));
+ AN2 U1341 ( .A(n1365), .B(n1366), .Z(n1363));
+ OR2 U1342 ( .A(n1188), .B(n857), .Z(n1366));
+ IV2 U1343 ( .A(n908), .Z(n857));
+ IV2 U1344 ( .A(n718), .Z(n1188));
+ AN2 U1345 ( .A(n1367), .B(n1368), .Z(n1365));
+ OR2 U1346 ( .A(n1346), .B(n1205), .Z(n1368));
+ IV2 U1347 ( .A(n1074), .Z(n1205));
+ IV2 U1348 ( .A(n751), .Z(n1346));
+ OR2 U1349 ( .A(n829), .B(n1041), .Z(n1367));
+ IV2 U1350 ( .A(n892), .Z(n829));
+ AN2 U1351 ( .A(n1309), .B(n1369), .Z(n937));
+ AN2 U1352 ( .A(pi13), .B(n751), .Z(n1369));
+ AN2 U1353 ( .A(n939), .B(n1370), .Z(n1325));
+ OR2 U1354 ( .A(n1371), .B(n1372), .Z(n1370));
+ OR2 U1355 ( .A(n1074), .B(n1373), .Z(n1372));
+ AN2 U1356 ( .A(n1374), .B(n944), .Z(n1373));
+ AN2 U1357 ( .A(n713), .B(n709), .Z(n1374));
+ AN2 U1358 ( .A(n1041), .B(pi00), .Z(n1074));
+ OR2 U1359 ( .A(n1375), .B(n1376), .Z(n1041));
+ OR2 U1360 ( .A(n1377), .B(n1378), .Z(n1376));
+ OR2 U1361 ( .A(n1379), .B(n1380), .Z(n1378));
+ AN2 U1362 ( .A(n949), .B(n709), .Z(n1380));
+ OR2 U1363 ( .A(n1381), .B(n1382), .Z(n949));
+ OR2 U1364 ( .A(n1383), .B(n1384), .Z(n1382));
+ AN2 U1365 ( .A(n751), .B(n963), .Z(n1384));
+ AN2 U1366 ( .A(n1385), .B(n860), .Z(n1383));
+ IV2 U1367 ( .A(n963), .Z(n860));
+ AN2 U1368 ( .A(n1386), .B(n924), .Z(n1381));
+ AN2 U1369 ( .A(n804), .B(n1361), .Z(n924));
+ AN2 U1370 ( .A(pi08), .B(pi10), .Z(n1386));
+ AN2 U1371 ( .A(n718), .B(n1140), .Z(n1379));
+ OR2 U1372 ( .A(n1387), .B(n981), .Z(n1140));
+ AN2 U1373 ( .A(pi11), .B(n1388), .Z(n981));
+ AN2 U1374 ( .A(n1023), .B(n1389), .Z(n1388));
+ OR2 U1375 ( .A(n751), .B(n892), .Z(n1389));
+ AN2 U1376 ( .A(n744), .B(n1361), .Z(n892));
+ AN2 U1377 ( .A(pi09), .B(pi08), .Z(n751));
+ AN2 U1378 ( .A(n944), .B(n1361), .Z(n1387));
+ AN2 U1379 ( .A(n744), .B(n963), .Z(n944));
+ AN2 U1380 ( .A(n784), .B(n1151), .Z(n1377));
+ AN2 U1381 ( .A(n713), .B(pi04), .Z(n1151));
+ AN2 U1382 ( .A(n973), .B(n902), .Z(n784));
+ AN2 U1383 ( .A(n963), .B(pi13), .Z(n902));
+ AN2 U1384 ( .A(n738), .B(pi10), .Z(n963));
+ OR2 U1385 ( .A(n1390), .B(n1391), .Z(n1375));
+ OR2 U1386 ( .A(n1392), .B(n1393), .Z(n1391));
+ AN2 U1387 ( .A(n950), .B(n1394), .Z(n1393));
+ OR2 U1388 ( .A(pi00), .B(pi04), .Z(n1394));
+ AN2 U1389 ( .A(n1395), .B(n908), .Z(n950));
+ AN2 U1390 ( .A(n1361), .B(pi08), .Z(n908));
+ IV2 U1391 ( .A(pi09), .Z(n1361));
+ OR2 U1392 ( .A(pi13), .B(n1309), .Z(n1395));
+ AN2 U1393 ( .A(n1023), .B(n738), .Z(n1309));
+ IV2 U1394 ( .A(pi11), .Z(n738));
+ AN2 U1395 ( .A(n1385), .B(n1316), .Z(n1392));
+ AN2 U1396 ( .A(n709), .B(pi00), .Z(n1316));
+ IV2 U1397 ( .A(pi04), .Z(n709));
+ AN2 U1398 ( .A(n973), .B(pi13), .Z(n1385));
+ AN2 U1399 ( .A(n744), .B(pi09), .Z(n973));
+ AN2 U1400 ( .A(n957), .B(n713), .Z(n1390));
+ IV2 U1401 ( .A(pi00), .Z(n713));
+ AN2 U1402 ( .A(n804), .B(n854), .Z(n957));
+ AN2 U1403 ( .A(n744), .B(n1023), .Z(n854));
+ IV2 U1404 ( .A(pi10), .Z(n1023));
+ AN2 U1405 ( .A(n718), .B(n982), .Z(n1371));
+ OR2 U1406 ( .A(n1396), .B(pi11), .Z(n982));
+ AN2 U1407 ( .A(pi10), .B(n744), .Z(n1396));
+ IV2 U1408 ( .A(pi08), .Z(n744));
+ AN2 U1409 ( .A(pi00), .B(pi04), .Z(n718));
+ AN2 U1410 ( .A(n804), .B(pi09), .Z(n939));
+ IV2 U1411 ( .A(pi13), .Z(n804));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/alu4.ys b/examples/smtbmc/glift/alu4.ys
new file mode 100644
index 000000000..8e8d14225
--- /dev/null
+++ b/examples/smtbmc/glift/alu4.ys
@@ -0,0 +1,41 @@
+read_verilog alu4.v
+techmap
+flatten
+select alu4_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename alu4_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog alu4.v
+techmap
+flatten
+select alu4_lev2
+glift -create-precise-model
+techmap
+opt
+rename alu4_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution alu4.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file alu4.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/examples/smtbmc/glift/mux2.ys b/examples/smtbmc/glift/mux2.ys
new file mode 100644
index 000000000..a8e99912b
--- /dev/null
+++ b/examples/smtbmc/glift/mux2.ys
@@ -0,0 +1,40 @@
+logger -expect log "SAT proof finished - no model found: SUCCESS!" 1
+logger -expect log "Number of cells:.*[\t ]12" 1
+logger -expect log "Number of cells:.*[\t ]20" 1
+logger -expect log "Problem is satisfiable with \\gate.__glift_weight = 11." 1
+logger -expect log "Problem is NOT satisfiable with \\gate.__glift_weight <= 10." 1
+logger -expect log "Wire \\gate.__glift_weight is minimized at 11." 1
+logger -expect log "Specializing .* from file with .* = 1." 2
+logger -expect log "Specializing .* from file with .* = 0." 4
+read_verilog <<EOT
+module mux2(a, b, s, y);
+ input a, b, s;
+ output y;
+
+ wire s_n = ~s;
+ wire t0 = s & a;
+ wire t1 = s_n & b;
+ assign y = t0 | t1;
+endmodule
+EOT
+techmap
+copy mux2 spec
+copy mux2 uut
+copy mux2 solved
+delete mux2
+glift -create-precise-model spec
+glift -create-instrumented-model uut
+glift -create-instrumented-model -no-cost-model solved
+design -push-copy
+miter -equiv spec uut qbfmiter
+flatten
+delete spec uut solved
+qbfsat -assume-outputs -assume-negative-polarity -write-solution mux2.soln qbfmiter
+design -pop
+qbfsat -specialize-from-file mux2.soln solved
+opt
+miter -equiv spec solved proofmiter
+flatten proofmiter
+sat -prove trigger 0 proofmiter
+delete proofmiter
+stat solved spec
diff --git a/examples/smtbmc/glift/t481.v b/examples/smtbmc/glift/t481.v
new file mode 100755
index 000000000..b23c8b211
--- /dev/null
+++ b/examples/smtbmc/glift/t481.v
@@ -0,0 +1,83 @@
+module t481_lev2(pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, po0);
+
+input pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15;
+
+output po0;
+
+wire n46, n47, n48, n49, n50, n51, n52, n53, n54, n55,
+ n56, n57, n58, n59, n60, n61, n62, n63, n64, n65,
+ n66, n67, n68, n69, n70, n71, n72, n73, n74, n75,
+ n76, n77, n78, n79, n80, n81, n82, n83, n84, n85,
+ n86, n87, n88, n89, n90;
+
+ OR2 U47 ( .A(n46), .B(n47), .Z(po0));
+ OR2 U48 ( .A(n48), .B(n49), .Z(n47));
+ AN2 U49 ( .A(n50), .B(n51), .Z(n49));
+ OR2 U50 ( .A(n52), .B(n53), .Z(n51));
+ AN2 U51 ( .A(n54), .B(n55), .Z(n53));
+ AN2 U52 ( .A(n56), .B(n57), .Z(n54));
+ AN2 U53 ( .A(n58), .B(n59), .Z(n52));
+ AN2 U54 ( .A(n60), .B(n61), .Z(n48));
+ IV2 U55 ( .A(n50), .Z(n61));
+ AN2 U56 ( .A(n62), .B(pi15), .Z(n50));
+ IV2 U57 ( .A(pi14), .Z(n62));
+ OR2 U58 ( .A(n63), .B(n64), .Z(n60));
+ AN2 U59 ( .A(n65), .B(n55), .Z(n64));
+ IV2 U60 ( .A(n59), .Z(n55));
+ AN2 U61 ( .A(n57), .B(n58), .Z(n65));
+ IV2 U62 ( .A(n56), .Z(n58));
+ AN2 U63 ( .A(n56), .B(n59), .Z(n63));
+ AN2 U64 ( .A(n66), .B(pi00), .Z(n56));
+ IV2 U65 ( .A(pi01), .Z(n66));
+ AN2 U66 ( .A(n67), .B(n59), .Z(n46));
+ OR2 U67 ( .A(n68), .B(n69), .Z(n59));
+ OR2 U68 ( .A(n70), .B(n71), .Z(n69));
+ AN2 U69 ( .A(n72), .B(n73), .Z(n71));
+ IV2 U70 ( .A(n74), .Z(n70));
+ OR2 U71 ( .A(n73), .B(n72), .Z(n74));
+ AN2 U72 ( .A(n75), .B(pi12), .Z(n72));
+ IV2 U73 ( .A(pi13), .Z(n75));
+ OR2 U74 ( .A(pi10), .B(n76), .Z(n73));
+ IV2 U75 ( .A(pi11), .Z(n76));
+ AN2 U76 ( .A(n77), .B(n78), .Z(n68));
+ OR2 U77 ( .A(n79), .B(n80), .Z(n78));
+ IV2 U78 ( .A(n81), .Z(n77));
+ AN2 U79 ( .A(n80), .B(n79), .Z(n81));
+ AN2 U80 ( .A(n82), .B(pi08), .Z(n79));
+ IV2 U81 ( .A(pi09), .Z(n82));
+ OR2 U82 ( .A(pi06), .B(n83), .Z(n80));
+ IV2 U83 ( .A(pi07), .Z(n83));
+ IV2 U84 ( .A(n57), .Z(n67));
+ OR2 U85 ( .A(n84), .B(n85), .Z(n57));
+ AN2 U86 ( .A(n86), .B(n87), .Z(n85));
+ IV2 U87 ( .A(n88), .Z(n84));
+ OR2 U88 ( .A(n87), .B(n86), .Z(n88));
+ AN2 U89 ( .A(n89), .B(pi04), .Z(n86));
+ IV2 U90 ( .A(pi05), .Z(n89));
+ OR2 U91 ( .A(pi02), .B(n90), .Z(n87));
+ IV2 U92 ( .A(pi03), .Z(n90));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/t481.ys b/examples/smtbmc/glift/t481.ys
new file mode 100644
index 000000000..0e4afffda
--- /dev/null
+++ b/examples/smtbmc/glift/t481.ys
@@ -0,0 +1,41 @@
+read_verilog t481.v
+techmap
+flatten
+select t481_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename t481_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog t481.v
+techmap
+flatten
+select t481_lev2
+glift -create-precise-model
+techmap
+opt
+rename t481_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution t481.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file t481.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/examples/smtbmc/glift/too_large.v b/examples/smtbmc/glift/too_large.v
new file mode 100755
index 000000000..67605cc34
--- /dev/null
+++ b/examples/smtbmc/glift/too_large.v
@@ -0,0 +1,345 @@
+module too_large_lev2(pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23, pi24, pi25, pi26, pi27, pi28, pi29,
+ pi30, pi31, pi32, pi33, pi34, pi35, pi36, pi37, po0, po1,
+ po2);
+
+input pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23, pi24, pi25, pi26, pi27, pi28, pi29,
+ pi30, pi31, pi32, pi33, pi34, pi35, pi36, pi37;
+
+output po0, po1, po2;
+
+wire n280, n281, n282, n283, n284, n285, n286, n287, n288, n289,
+ n290, n291, n292, n293, n294, n295, n296, n297, n298, n299,
+ n300, n301, n302, n303, n304, n305, n306, n307, n308, n309,
+ n310, n311, n312, n313, n314, n315, n316, n317, n318, n319,
+ n320, n321, n322, n323, n324, n325, n326, n327, n328, n329,
+ n330, n331, n332, n333, n334, n335, n336, n337, n338, n339,
+ n340, n341, n342, n343, n344, n345, n346, n347, n348, n349,
+ n350, n351, n352, n353, n354, n355, n356, n357, n358, n359,
+ n360, n361, n362, n363, n364, n365, n366, n367, n368, n369,
+ n370, n371, n372, n373, n374, n375, n376, n377, n378, n379,
+ n380, n381, n382, n383, n384, n385, n386, n387, n388, n389,
+ n390, n391, n392, n393, n394, n395, n396, n397, n398, n399,
+ n400, n401, n402, n403, n404, n405, n406, n407, n408, n409,
+ n410, n411, n412, n413, n414, n415, n416, n417, n418, n419,
+ n420, n421, n422, n423, n424, n425, n426, n427, n428, n429,
+ n430, n431, n432, n433, n434, n435, n436, n437, n438, n439,
+ n440, n441, n442, n443, n444, n445, n446, n447, n448, n449,
+ n450, n451, n452, n453, n454, n455, n456, n457, n458, n459,
+ n460, n461, n462, n463, n464, n465, n466, n467, n468, n469,
+ n470, n471, n472, n473, n474, n475, n476, n477, n478, n479,
+ n480, n481, n482, n483, n484, n485, n486, n487, n488, n489,
+ n490, n491, n492, n493, n494, n495, n496, n497, n498, n499,
+ n500, n501, n502, n503, n504, n505, n506, n507, n508, n509,
+ n510, n511, n512, n513, n514, n515, n516, n517, n518, n519,
+ n520, n521, n522, n523, n524, n525, n526, n527, n528, n529,
+ n530, n531, n532, n533, n534, n535, n536, n537, n538, n539,
+ n540, n541, n542, n543, n544, n545, n546, n547, n548, n549,
+ n550, n551, n552, n553, n554, n555, n556;
+
+ AN2 U283 ( .A(n280), .B(n281), .Z(po2));
+ OR2 U284 ( .A(n282), .B(n283), .Z(n280));
+ OR2 U285 ( .A(n284), .B(n285), .Z(n283));
+ AN2 U286 ( .A(n286), .B(n287), .Z(n285));
+ OR2 U287 ( .A(n288), .B(n289), .Z(n287));
+ OR2 U288 ( .A(n290), .B(n291), .Z(n289));
+ AN2 U289 ( .A(pi29), .B(n292), .Z(n291));
+ AN2 U290 ( .A(n293), .B(pi35), .Z(n290));
+ AN2 U291 ( .A(n294), .B(n295), .Z(n293));
+ OR2 U292 ( .A(pi29), .B(n296), .Z(n294));
+ AN2 U293 ( .A(n297), .B(pi18), .Z(n284));
+ AN2 U294 ( .A(n298), .B(n299), .Z(n297));
+ IV2 U295 ( .A(n300), .Z(n299));
+ OR2 U296 ( .A(n301), .B(n302), .Z(n298));
+ AN2 U297 ( .A(n303), .B(n304), .Z(n302));
+ OR2 U298 ( .A(n305), .B(n306), .Z(n304));
+ AN2 U299 ( .A(n307), .B(n308), .Z(n306));
+ AN2 U300 ( .A(n309), .B(n310), .Z(n305));
+ OR2 U301 ( .A(n311), .B(n312), .Z(n310));
+ AN2 U302 ( .A(n308), .B(n313), .Z(n312));
+ OR2 U303 ( .A(n314), .B(n315), .Z(n308));
+ AN2 U304 ( .A(n316), .B(n317), .Z(n311));
+ AN2 U305 ( .A(n318), .B(n319), .Z(n317));
+ AN2 U306 ( .A(pi15), .B(n315), .Z(n316));
+ OR2 U307 ( .A(n320), .B(n321), .Z(n315));
+ AN2 U308 ( .A(n322), .B(n323), .Z(n309));
+ OR2 U309 ( .A(n324), .B(n325), .Z(n322));
+ AN2 U310 ( .A(n326), .B(n327), .Z(n301));
+ OR2 U311 ( .A(n328), .B(n307), .Z(n327));
+ AN2 U312 ( .A(n329), .B(n323), .Z(n328));
+ OR2 U313 ( .A(n330), .B(n331), .Z(n329));
+ AN2 U314 ( .A(n332), .B(n313), .Z(n331));
+ OR2 U315 ( .A(n333), .B(n325), .Z(n332));
+ AN2 U316 ( .A(n324), .B(n334), .Z(n333));
+ IV2 U317 ( .A(n335), .Z(n334));
+ AN2 U318 ( .A(n336), .B(pi08), .Z(n335));
+ OR2 U319 ( .A(n320), .B(n314), .Z(n336));
+ AN2 U320 ( .A(n337), .B(n338), .Z(n314));
+ OR2 U321 ( .A(pi20), .B(n339), .Z(n337));
+ AN2 U322 ( .A(n340), .B(n341), .Z(n330));
+ AN2 U323 ( .A(n342), .B(n319), .Z(n341));
+ OR2 U324 ( .A(n343), .B(n325), .Z(n342));
+ AN2 U325 ( .A(n324), .B(n344), .Z(n343));
+ IV2 U326 ( .A(n345), .Z(n344));
+ AN2 U327 ( .A(n346), .B(n295), .Z(n324));
+ AN2 U328 ( .A(pi15), .B(n318), .Z(n340));
+ OR2 U329 ( .A(n347), .B(n348), .Z(n318));
+ AN2 U330 ( .A(n349), .B(n350), .Z(n347));
+ AN2 U331 ( .A(n351), .B(n352), .Z(n326));
+ OR2 U332 ( .A(n353), .B(n354), .Z(n282));
+ AN2 U333 ( .A(n355), .B(n356), .Z(n354));
+ AN2 U334 ( .A(n357), .B(n358), .Z(n355));
+ OR2 U335 ( .A(pi26), .B(pi27), .Z(n357));
+ AN2 U336 ( .A(n359), .B(n360), .Z(n353));
+ OR2 U337 ( .A(n361), .B(n362), .Z(n360));
+ AN2 U338 ( .A(n288), .B(n363), .Z(n362));
+ OR2 U339 ( .A(n364), .B(n365), .Z(n288));
+ AN2 U340 ( .A(n292), .B(n296), .Z(n364));
+ OR2 U341 ( .A(n366), .B(n367), .Z(n296));
+ IV2 U342 ( .A(n368), .Z(n367));
+ AN2 U343 ( .A(n369), .B(n370), .Z(n368));
+ OR2 U344 ( .A(pi33), .B(pi22), .Z(n366));
+ AN2 U345 ( .A(pi29), .B(n371), .Z(n361));
+ OR2 U346 ( .A(n372), .B(n373), .Z(n371));
+ AN2 U347 ( .A(n374), .B(n292), .Z(n372));
+ IV2 U348 ( .A(n356), .Z(n359));
+ AN2 U349 ( .A(n295), .B(pi35), .Z(n356));
+ IV2 U350 ( .A(pi28), .Z(n295));
+ OR2 U351 ( .A(n375), .B(n376), .Z(po1));
+ OR2 U352 ( .A(n377), .B(n378), .Z(n376));
+ AN2 U353 ( .A(n379), .B(n380), .Z(n378));
+ AN2 U354 ( .A(n381), .B(n382), .Z(n380));
+ IV2 U355 ( .A(n365), .Z(n382));
+ AN2 U356 ( .A(n383), .B(pi05), .Z(n379));
+ AN2 U357 ( .A(n384), .B(n385), .Z(n377));
+ OR2 U358 ( .A(n386), .B(n387), .Z(n385));
+ AN2 U359 ( .A(n388), .B(n369), .Z(n387));
+ OR2 U360 ( .A(n389), .B(n390), .Z(n388));
+ AN2 U361 ( .A(n391), .B(n370), .Z(n390));
+ OR2 U362 ( .A(n392), .B(n393), .Z(n391));
+ OR2 U363 ( .A(n394), .B(n395), .Z(n393));
+ AN2 U364 ( .A(n396), .B(pi35), .Z(n395));
+ AN2 U365 ( .A(n397), .B(n358), .Z(n396));
+ AN2 U366 ( .A(n398), .B(n399), .Z(n394));
+ IV2 U367 ( .A(n400), .Z(n399));
+ AN2 U368 ( .A(n286), .B(pi08), .Z(n398));
+ AN2 U369 ( .A(n401), .B(n402), .Z(n392));
+ OR2 U370 ( .A(n403), .B(n286), .Z(n402));
+ AN2 U371 ( .A(n400), .B(n363), .Z(n403));
+ OR2 U372 ( .A(n404), .B(n300), .Z(n401));
+ AN2 U373 ( .A(pi37), .B(pi13), .Z(n404));
+ AN2 U374 ( .A(n405), .B(n406), .Z(n389));
+ AN2 U375 ( .A(n407), .B(n352), .Z(n406));
+ AN2 U376 ( .A(pi05), .B(n408), .Z(n405));
+ OR2 U377 ( .A(n409), .B(n410), .Z(n408));
+ AN2 U378 ( .A(n411), .B(n351), .Z(n410));
+ AN2 U379 ( .A(n412), .B(n413), .Z(n409));
+ OR2 U380 ( .A(n414), .B(n415), .Z(n412));
+ AN2 U381 ( .A(n416), .B(n351), .Z(n415));
+ OR2 U382 ( .A(n417), .B(n418), .Z(n416));
+ AN2 U383 ( .A(n286), .B(n319), .Z(n417));
+ AN2 U384 ( .A(n419), .B(n420), .Z(n414));
+ AN2 U385 ( .A(pi02), .B(n421), .Z(n419));
+ AN2 U386 ( .A(n422), .B(n423), .Z(n386));
+ AN2 U387 ( .A(n424), .B(n425), .Z(n423));
+ OR2 U388 ( .A(n426), .B(n427), .Z(n425));
+ AN2 U389 ( .A(n428), .B(n429), .Z(n427));
+ AN2 U390 ( .A(n430), .B(n407), .Z(n426));
+ IV2 U391 ( .A(n431), .Z(n407));
+ AN2 U392 ( .A(n432), .B(pi21), .Z(n431));
+ OR2 U393 ( .A(pi01), .B(pi20), .Z(n432));
+ OR2 U394 ( .A(n433), .B(n434), .Z(n430));
+ AN2 U395 ( .A(n429), .B(n339), .Z(n433));
+ OR2 U396 ( .A(n435), .B(n411), .Z(n424));
+ AN2 U397 ( .A(n436), .B(n437), .Z(n411));
+ AN2 U398 ( .A(n438), .B(n286), .Z(n437));
+ IV2 U399 ( .A(n439), .Z(n436));
+ OR2 U400 ( .A(pi26), .B(pi06), .Z(n439));
+ AN2 U401 ( .A(pi05), .B(n303), .Z(n422));
+ AN2 U402 ( .A(n440), .B(n441), .Z(n375));
+ OR2 U403 ( .A(n442), .B(n443), .Z(n441));
+ AN2 U404 ( .A(pi35), .B(n397), .Z(n443));
+ OR2 U405 ( .A(pi27), .B(pi28), .Z(n397));
+ AN2 U406 ( .A(n300), .B(n400), .Z(n442));
+ OR2 U407 ( .A(pi26), .B(n413), .Z(n400));
+ OR2 U408 ( .A(n444), .B(n445), .Z(po0));
+ OR2 U409 ( .A(n446), .B(n447), .Z(n445));
+ AN2 U410 ( .A(n448), .B(pi04), .Z(n447));
+ AN2 U411 ( .A(n383), .B(n381), .Z(n448));
+ OR2 U412 ( .A(n449), .B(n450), .Z(n381));
+ AN2 U413 ( .A(n420), .B(n451), .Z(n450));
+ AN2 U414 ( .A(n452), .B(n453), .Z(n449));
+ OR2 U415 ( .A(n454), .B(n374), .Z(n452));
+ AN2 U416 ( .A(n373), .B(n455), .Z(n454));
+ AN2 U417 ( .A(n456), .B(n457), .Z(n383));
+ AN2 U418 ( .A(n413), .B(n281), .Z(n457));
+ AN2 U419 ( .A(n384), .B(n458), .Z(n446));
+ OR2 U420 ( .A(n459), .B(n460), .Z(n458));
+ OR2 U421 ( .A(n461), .B(n462), .Z(n460));
+ AN2 U422 ( .A(n463), .B(n369), .Z(n462));
+ OR2 U423 ( .A(n464), .B(n465), .Z(n463));
+ AN2 U424 ( .A(n466), .B(n467), .Z(n465));
+ OR2 U425 ( .A(n468), .B(n469), .Z(n467));
+ OR2 U426 ( .A(n470), .B(n471), .Z(n469));
+ AN2 U427 ( .A(n365), .B(n350), .Z(n471));
+ AN2 U428 ( .A(n472), .B(pi37), .Z(n470));
+ AN2 U429 ( .A(pi13), .B(n473), .Z(n472));
+ OR2 U430 ( .A(n474), .B(n475), .Z(n473));
+ AN2 U431 ( .A(n370), .B(n338), .Z(n475));
+ AN2 U432 ( .A(pi16), .B(n476), .Z(n474));
+ OR2 U433 ( .A(n477), .B(n428), .Z(n476));
+ AN2 U434 ( .A(n478), .B(n350), .Z(n477));
+ AN2 U435 ( .A(n300), .B(n479), .Z(n468));
+ OR2 U436 ( .A(n480), .B(n286), .Z(n466));
+ AN2 U437 ( .A(n481), .B(n363), .Z(n480));
+ AN2 U438 ( .A(n482), .B(n483), .Z(n464));
+ AN2 U439 ( .A(n370), .B(n358), .Z(n482));
+ AN2 U440 ( .A(n484), .B(n485), .Z(n461));
+ AN2 U441 ( .A(n286), .B(n486), .Z(n484));
+ OR2 U442 ( .A(n487), .B(n488), .Z(n486));
+ AN2 U443 ( .A(n489), .B(n370), .Z(n488));
+ OR2 U444 ( .A(n490), .B(n345), .Z(n489));
+ AN2 U445 ( .A(n320), .B(pi08), .Z(n345));
+ AN2 U446 ( .A(pi06), .B(n369), .Z(n490));
+ AN2 U447 ( .A(n491), .B(n429), .Z(n487));
+ AN2 U448 ( .A(pi08), .B(n492), .Z(n491));
+ AN2 U449 ( .A(pi04), .B(n493), .Z(n459));
+ OR2 U450 ( .A(n494), .B(n495), .Z(n493));
+ AN2 U451 ( .A(n303), .B(n496), .Z(n495));
+ OR2 U452 ( .A(n497), .B(n498), .Z(n496));
+ AN2 U453 ( .A(n499), .B(n500), .Z(n498));
+ OR2 U454 ( .A(n501), .B(n307), .Z(n500));
+ AN2 U455 ( .A(n374), .B(n502), .Z(n307));
+ AN2 U456 ( .A(n413), .B(n453), .Z(n502));
+ AN2 U457 ( .A(n503), .B(n313), .Z(n501));
+ OR2 U458 ( .A(n504), .B(n505), .Z(n503));
+ AN2 U459 ( .A(n325), .B(n323), .Z(n504));
+ AN2 U460 ( .A(n413), .B(n506), .Z(n325));
+ AN2 U461 ( .A(n434), .B(n370), .Z(n499));
+ OR2 U462 ( .A(n507), .B(n320), .Z(n434));
+ AN2 U463 ( .A(n321), .B(n508), .Z(n507));
+ IV2 U464 ( .A(pi07), .Z(n321));
+ AN2 U465 ( .A(n509), .B(n429), .Z(n497));
+ AN2 U466 ( .A(n508), .B(n338), .Z(n429));
+ IV2 U467 ( .A(pi15), .Z(n338));
+ AN2 U468 ( .A(n510), .B(n492), .Z(n509));
+ OR2 U469 ( .A(n511), .B(n428), .Z(n492));
+ AN2 U470 ( .A(n479), .B(pi20), .Z(n428));
+ AN2 U471 ( .A(n339), .B(n350), .Z(n511));
+ OR2 U472 ( .A(n478), .B(n348), .Z(n339));
+ IV2 U473 ( .A(pi16), .Z(n348));
+ IV2 U474 ( .A(n349), .Z(n478));
+ AN2 U475 ( .A(n512), .B(n513), .Z(n349));
+ OR2 U476 ( .A(pi25), .B(pi17), .Z(n513));
+ OR2 U477 ( .A(n514), .B(pi24), .Z(n512));
+ IV2 U478 ( .A(pi09), .Z(n514));
+ OR2 U479 ( .A(n515), .B(n435), .Z(n510));
+ AN2 U480 ( .A(n516), .B(n413), .Z(n435));
+ OR2 U481 ( .A(n517), .B(n418), .Z(n516));
+ AN2 U482 ( .A(n363), .B(n453), .Z(n418));
+ OR2 U483 ( .A(n373), .B(n374), .Z(n363));
+ AN2 U484 ( .A(n323), .B(pi02), .Z(n373));
+ AN2 U485 ( .A(n505), .B(n438), .Z(n515));
+ OR2 U486 ( .A(n453), .B(n319), .Z(n438));
+ IV2 U487 ( .A(n518), .Z(n303));
+ OR2 U488 ( .A(n519), .B(n520), .Z(n518));
+ OR2 U489 ( .A(pi08), .B(n521), .Z(n520));
+ OR2 U490 ( .A(pi10), .B(n522), .Z(n519));
+ OR2 U491 ( .A(pi12), .B(pi11), .Z(n522));
+ AN2 U492 ( .A(n523), .B(n524), .Z(n494));
+ OR2 U493 ( .A(n525), .B(n526), .Z(n524));
+ AN2 U494 ( .A(n527), .B(n528), .Z(n526));
+ OR2 U495 ( .A(n529), .B(n530), .Z(n528));
+ AN2 U496 ( .A(n531), .B(n351), .Z(n530));
+ AN2 U497 ( .A(n358), .B(n453), .Z(n531));
+ OR2 U498 ( .A(n532), .B(n374), .Z(n358));
+ AN2 U499 ( .A(n506), .B(n323), .Z(n532));
+ AN2 U500 ( .A(n517), .B(n533), .Z(n529));
+ AN2 U501 ( .A(n421), .B(n534), .Z(n533));
+ IV2 U502 ( .A(pi14), .Z(n421));
+ AN2 U503 ( .A(n420), .B(n506), .Z(n517));
+ OR2 U504 ( .A(pi02), .B(n346), .Z(n506));
+ AN2 U505 ( .A(n323), .B(n319), .Z(n420));
+ AN2 U506 ( .A(n369), .B(n413), .Z(n527));
+ OR2 U507 ( .A(n320), .B(n508), .Z(n369));
+ AN2 U508 ( .A(n535), .B(n536), .Z(n525));
+ AN2 U509 ( .A(n313), .B(n351), .Z(n536));
+ IV2 U510 ( .A(n521), .Z(n351));
+ AN2 U511 ( .A(pi00), .B(pi14), .Z(n521));
+ OR2 U512 ( .A(n537), .B(n453), .Z(n313));
+ IV2 U513 ( .A(pi13), .Z(n453));
+ AN2 U514 ( .A(n319), .B(n534), .Z(n537));
+ IV2 U515 ( .A(pi37), .Z(n534));
+ IV2 U516 ( .A(pi03), .Z(n319));
+ AN2 U517 ( .A(n505), .B(n538), .Z(n535));
+ OR2 U518 ( .A(n539), .B(n320), .Z(n538));
+ IV2 U519 ( .A(pi19), .Z(n320));
+ AN2 U520 ( .A(n540), .B(n508), .Z(n539));
+ IV2 U521 ( .A(pi23), .Z(n508));
+ IV2 U522 ( .A(pi08), .Z(n540));
+ AN2 U523 ( .A(n541), .B(n286), .Z(n505));
+ AN2 U524 ( .A(n346), .B(n323), .Z(n286));
+ IV2 U525 ( .A(pi27), .Z(n541));
+ AN2 U526 ( .A(n370), .B(n352), .Z(n523));
+ IV2 U527 ( .A(pi36), .Z(n352));
+ OR2 U528 ( .A(n350), .B(n479), .Z(n370));
+ IV2 U529 ( .A(pi21), .Z(n479));
+ IV2 U530 ( .A(pi20), .Z(n350));
+ IV2 U531 ( .A(n542), .Z(n384));
+ OR2 U532 ( .A(n543), .B(n544), .Z(n542));
+ OR2 U533 ( .A(pi29), .B(pi22), .Z(n544));
+ OR2 U534 ( .A(pi34), .B(pi33), .Z(n543));
+ AN2 U535 ( .A(n440), .B(n545), .Z(n444));
+ OR2 U536 ( .A(n546), .B(n483), .Z(n545));
+ OR2 U537 ( .A(n547), .B(n548), .Z(n483));
+ AN2 U538 ( .A(pi28), .B(pi35), .Z(n548));
+ AN2 U539 ( .A(pi26), .B(n485), .Z(n547));
+ IV2 U540 ( .A(n481), .Z(n485));
+ AN2 U541 ( .A(n549), .B(n481), .Z(n546));
+ OR2 U542 ( .A(pi27), .B(n413), .Z(n481));
+ IV2 U543 ( .A(pi35), .Z(n413));
+ OR2 U544 ( .A(n365), .B(n300), .Z(n549));
+ AN2 U545 ( .A(pi01), .B(pi31), .Z(n300));
+ AN2 U546 ( .A(pi01), .B(pi21), .Z(n365));
+ AN2 U547 ( .A(n456), .B(n550), .Z(n440));
+ AN2 U548 ( .A(n281), .B(n551), .Z(n550));
+ OR2 U549 ( .A(n374), .B(n552), .Z(n551));
+ AN2 U550 ( .A(n323), .B(n451), .Z(n552));
+ OR2 U551 ( .A(n553), .B(n554), .Z(n451));
+ AN2 U552 ( .A(n555), .B(n346), .Z(n554));
+ IV2 U553 ( .A(pi32), .Z(n346));
+ AN2 U554 ( .A(pi02), .B(n455), .Z(n553));
+ IV2 U555 ( .A(pi29), .Z(n455));
+ IV2 U556 ( .A(pi30), .Z(n323));
+ AN2 U557 ( .A(n555), .B(pi03), .Z(n374));
+ IV2 U558 ( .A(pi02), .Z(n555));
+ IV2 U559 ( .A(pi34), .Z(n281));
+ IV2 U560 ( .A(n292), .Z(n456));
+ OR2 U561 ( .A(pi00), .B(n556), .Z(n292));
+ OR2 U562 ( .A(pi37), .B(pi36), .Z(n556));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/too_large.ys b/examples/smtbmc/glift/too_large.ys
new file mode 100644
index 000000000..77be61e17
--- /dev/null
+++ b/examples/smtbmc/glift/too_large.ys
@@ -0,0 +1,41 @@
+read_verilog too_large.v
+techmap
+flatten
+select too_large_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename too_large_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog too_large.v
+techmap
+flatten
+select too_large_lev2
+glift -create-precise-model
+techmap
+opt
+rename too_large_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution too_large.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file too_large.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/examples/smtbmc/glift/ttt2.v b/examples/smtbmc/glift/ttt2.v
new file mode 100755
index 000000000..47ca7684a
--- /dev/null
+++ b/examples/smtbmc/glift/ttt2.v
@@ -0,0 +1,220 @@
+module ttt2_lev2(pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23, po00, po01, po02, po03, po04, po05,
+ po06, po07, po08, po09, po10, po11, po12, po13, po14, po15,
+ po16, po17, po18, po19, po20);
+
+input pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23;
+
+output po00, po01, po02, po03, po04, po05, po06, po07, po08, po09,
+ po10, po11, po12, po13, po14, po15, po16, po17, po18, po19,
+ po20;
+
+wire n148, n149, n150, n151, n152, n153, n154, n155, n156, n157,
+ n158, n159, n160, n161, n162, n163, n164, n165, n166, n167,
+ n168, n169, n170, n171, n172, n173, n174, n175, n176, n177,
+ n178, n179, n180, n181, n182, n183, n184, n185, n186, n187,
+ n188, n189, n190, n191, n192, n193, n194, n195, n196, n197,
+ n198, n199, n200, n201, n202, n203, n204, n205, n206, n207,
+ n208, n209, n210, n211, n212, n213, n214, n215, n216, n217,
+ n218, n219, n220, n221, n222, n223, n224, n225, n226, n227,
+ n228, n229, n230, n231, n232, n233, n234, n235, n236, n237,
+ n238, n239, n240, n241, n242, n243, n244, n245, n246, n247,
+ n248, n249, n250, n251, n252, n253, n254, n255, n256, n257,
+ n258, n259, n260, n261, n262, n263, n264, n265, n266, n267,
+ n268, n269, n270, n271, n272, n273, n274, n275, n276, n277,
+ n278, n279, n280, n281, n282, n283, n284, n285, n286, n287,
+ n288, n289, n290, n291, n292, n293;
+
+ AN2 U168 ( .A(n148), .B(n149), .Z(po20));
+ OR2 U169 ( .A(n150), .B(n151), .Z(n148));
+ AN2 U170 ( .A(pi02), .B(n152), .Z(n151));
+ IV2 U171 ( .A(n153), .Z(n150));
+ OR2 U172 ( .A(n152), .B(pi02), .Z(n153));
+ IV2 U173 ( .A(pi23), .Z(n152));
+ AN2 U174 ( .A(n154), .B(n149), .Z(po19));
+ OR2 U175 ( .A(n155), .B(n156), .Z(n154));
+ AN2 U176 ( .A(pi01), .B(n157), .Z(n156));
+ AN2 U177 ( .A(pi22), .B(n158), .Z(n155));
+ IV2 U178 ( .A(pi01), .Z(n158));
+ AN2 U179 ( .A(n159), .B(n149), .Z(po18));
+ OR2 U180 ( .A(n160), .B(n161), .Z(po17));
+ AN2 U181 ( .A(pi20), .B(n162), .Z(n161));
+ OR2 U182 ( .A(n163), .B(n164), .Z(n162));
+ OR2 U183 ( .A(n165), .B(n166), .Z(n164));
+ AN2 U184 ( .A(n167), .B(pi18), .Z(n166));
+ AN2 U185 ( .A(n149), .B(n168), .Z(n167));
+ AN2 U186 ( .A(n169), .B(n170), .Z(n160));
+ AN2 U187 ( .A(n171), .B(n172), .Z(n169));
+ OR2 U188 ( .A(n165), .B(n173), .Z(po16));
+ OR2 U189 ( .A(n174), .B(n175), .Z(n173));
+ AN2 U190 ( .A(n176), .B(n168), .Z(n175));
+ AN2 U191 ( .A(n170), .B(n171), .Z(n176));
+ AN2 U192 ( .A(pi19), .B(n163), .Z(n174));
+ AN2 U193 ( .A(pi19), .B(n177), .Z(n165));
+ AN2 U194 ( .A(n178), .B(n149), .Z(n177));
+ OR2 U195 ( .A(n179), .B(n180), .Z(po15));
+ AN2 U196 ( .A(n181), .B(n178), .Z(n180));
+ AN2 U197 ( .A(n182), .B(n170), .Z(n181));
+ AN2 U198 ( .A(pi17), .B(n183), .Z(n182));
+ OR2 U199 ( .A(pi19), .B(n184), .Z(n183));
+ AN2 U200 ( .A(pi18), .B(n163), .Z(n179));
+ OR2 U201 ( .A(n185), .B(n186), .Z(n163));
+ AN2 U202 ( .A(n149), .B(n187), .Z(n185));
+ OR2 U203 ( .A(n188), .B(n189), .Z(po14));
+ AN2 U204 ( .A(pi17), .B(n186), .Z(n189));
+ OR2 U205 ( .A(n190), .B(n191), .Z(n186));
+ AN2 U206 ( .A(n192), .B(n149), .Z(n190));
+ OR2 U207 ( .A(pi14), .B(n193), .Z(n192));
+ AN2 U208 ( .A(n170), .B(n187), .Z(n188));
+ AN2 U209 ( .A(n194), .B(n195), .Z(n170));
+ AN2 U210 ( .A(n196), .B(n197), .Z(n195));
+ OR2 U211 ( .A(n198), .B(n199), .Z(po13));
+ AN2 U212 ( .A(pi16), .B(n200), .Z(n199));
+ OR2 U213 ( .A(n201), .B(n191), .Z(n200));
+ AN2 U214 ( .A(n202), .B(pi14), .Z(n198));
+ AN2 U215 ( .A(n203), .B(n149), .Z(n202));
+ OR2 U216 ( .A(n204), .B(n197), .Z(n203));
+ IV2 U217 ( .A(n193), .Z(n197));
+ AN2 U218 ( .A(n205), .B(n206), .Z(n204));
+ AN2 U219 ( .A(n207), .B(n208), .Z(n206));
+ AN2 U220 ( .A(pi15), .B(pi13), .Z(n205));
+ OR2 U221 ( .A(n201), .B(n209), .Z(po12));
+ OR2 U222 ( .A(n210), .B(n211), .Z(n209));
+ AN2 U223 ( .A(n212), .B(n213), .Z(n211));
+ AN2 U224 ( .A(pi14), .B(n194), .Z(n212));
+ AN2 U225 ( .A(pi15), .B(n191), .Z(n210));
+ AN2 U226 ( .A(pi15), .B(n214), .Z(n201));
+ AN2 U227 ( .A(n196), .B(n149), .Z(n214));
+ OR2 U228 ( .A(n215), .B(n216), .Z(po11));
+ AN2 U229 ( .A(n217), .B(n196), .Z(n216));
+ IV2 U230 ( .A(pi14), .Z(n196));
+ AN2 U231 ( .A(n194), .B(n193), .Z(n217));
+ OR2 U232 ( .A(pi15), .B(n208), .Z(n193));
+ IV2 U233 ( .A(pi16), .Z(n208));
+ AN2 U234 ( .A(pi13), .B(n218), .Z(n194));
+ AN2 U235 ( .A(pi14), .B(n191), .Z(n215));
+ OR2 U236 ( .A(n219), .B(n220), .Z(n191));
+ AN2 U237 ( .A(n149), .B(n221), .Z(n220));
+ OR2 U238 ( .A(n222), .B(n223), .Z(po10));
+ AN2 U239 ( .A(n219), .B(pi13), .Z(n223));
+ AN2 U240 ( .A(n224), .B(n157), .Z(n219));
+ IV2 U241 ( .A(pi22), .Z(n157));
+ OR2 U242 ( .A(n225), .B(n226), .Z(n224));
+ OR2 U243 ( .A(po06), .B(n227), .Z(n226));
+ AN2 U244 ( .A(n218), .B(n221), .Z(n222));
+ IV2 U245 ( .A(pi13), .Z(n221));
+ AN2 U246 ( .A(n207), .B(n149), .Z(n218));
+ OR2 U247 ( .A(n228), .B(pi22), .Z(n207));
+ AN2 U248 ( .A(n229), .B(pi09), .Z(n228));
+ AN2 U249 ( .A(n230), .B(n231), .Z(n229));
+ OR2 U250 ( .A(n232), .B(n233), .Z(po09));
+ AN2 U251 ( .A(pi12), .B(n234), .Z(n233));
+ OR2 U252 ( .A(n235), .B(po06), .Z(n234));
+ AN2 U253 ( .A(n227), .B(n236), .Z(n232));
+ OR2 U254 ( .A(n237), .B(n230), .Z(n236));
+ AN2 U255 ( .A(n238), .B(pi11), .Z(n237));
+ AN2 U256 ( .A(pi09), .B(n239), .Z(n238));
+ IV2 U257 ( .A(pi12), .Z(n239));
+ OR2 U258 ( .A(n235), .B(n240), .Z(po08));
+ OR2 U259 ( .A(n241), .B(n242), .Z(n240));
+ AN2 U260 ( .A(po06), .B(pi11), .Z(n242));
+ AN2 U261 ( .A(n243), .B(n244), .Z(n241));
+ AN2 U262 ( .A(n227), .B(pi09), .Z(n243));
+ AN2 U263 ( .A(n149), .B(pi10), .Z(n227));
+ AN2 U264 ( .A(pi11), .B(n245), .Z(n235));
+ AN2 U265 ( .A(n231), .B(n149), .Z(n245));
+ OR2 U266 ( .A(n246), .B(n247), .Z(po07));
+ AN2 U267 ( .A(po06), .B(pi10), .Z(n247));
+ AN2 U268 ( .A(n248), .B(n231), .Z(n246));
+ IV2 U269 ( .A(pi10), .Z(n231));
+ AN2 U270 ( .A(n225), .B(pi09), .Z(n248));
+ AN2 U271 ( .A(n249), .B(n149), .Z(n225));
+ IV2 U272 ( .A(n230), .Z(n249));
+ AN2 U273 ( .A(n244), .B(pi12), .Z(n230));
+ IV2 U274 ( .A(pi11), .Z(n244));
+ AN2 U275 ( .A(n250), .B(n149), .Z(po06));
+ IV2 U276 ( .A(pi00), .Z(n149));
+ IV2 U277 ( .A(pi09), .Z(n250));
+ AN2 U278 ( .A(n251), .B(n252), .Z(po05));
+ OR2 U279 ( .A(n253), .B(n254), .Z(n251));
+ OR2 U280 ( .A(n255), .B(n256), .Z(n254));
+ AN2 U281 ( .A(n257), .B(n187), .Z(n255));
+ AN2 U282 ( .A(pi08), .B(n258), .Z(n253));
+ OR2 U283 ( .A(n259), .B(n260), .Z(po04));
+ AN2 U284 ( .A(pi07), .B(n261), .Z(n260));
+ AN2 U285 ( .A(n262), .B(n257), .Z(n259));
+ AN2 U286 ( .A(n171), .B(n252), .Z(n262));
+ AN2 U287 ( .A(pi17), .B(pi18), .Z(n171));
+ OR2 U288 ( .A(n263), .B(n264), .Z(po03));
+ OR2 U289 ( .A(n265), .B(n266), .Z(n264));
+ AN2 U290 ( .A(pi06), .B(n261), .Z(n266));
+ AN2 U291 ( .A(n267), .B(n213), .Z(n265));
+ OR2 U292 ( .A(n172), .B(pi21), .Z(n267));
+ OR2 U293 ( .A(n268), .B(n269), .Z(n263));
+ OR2 U294 ( .A(n270), .B(n269), .Z(po02));
+ IV2 U295 ( .A(n271), .Z(n269));
+ OR2 U296 ( .A(n272), .B(n273), .Z(n271));
+ AN2 U297 ( .A(n274), .B(n275), .Z(n272));
+ OR2 U298 ( .A(n187), .B(n276), .Z(n275));
+ OR2 U299 ( .A(pi21), .B(n277), .Z(n274));
+ AN2 U300 ( .A(pi05), .B(n261), .Z(n270));
+ OR2 U301 ( .A(n278), .B(n279), .Z(po01));
+ OR2 U302 ( .A(n268), .B(n280), .Z(n279));
+ AN2 U303 ( .A(pi04), .B(n261), .Z(n280));
+ AN2 U304 ( .A(n252), .B(n258), .Z(n261));
+ IV2 U305 ( .A(n281), .Z(n268));
+ OR2 U306 ( .A(n282), .B(n283), .Z(n281));
+ OR2 U307 ( .A(n184), .B(n284), .Z(n283));
+ OR2 U308 ( .A(pi21), .B(pi17), .Z(n282));
+ AN2 U309 ( .A(n159), .B(n213), .Z(n278));
+ IV2 U310 ( .A(pi15), .Z(n213));
+ OR2 U311 ( .A(n285), .B(n286), .Z(n159));
+ AN2 U312 ( .A(pi21), .B(n287), .Z(n286));
+ OR2 U313 ( .A(n276), .B(n288), .Z(n287));
+ OR2 U314 ( .A(n273), .B(n187), .Z(n288));
+ OR2 U315 ( .A(pi23), .B(pi18), .Z(n276));
+ AN2 U316 ( .A(n172), .B(n277), .Z(n285));
+ AN2 U317 ( .A(pi23), .B(n289), .Z(n277));
+ AN2 U318 ( .A(n178), .B(n187), .Z(n289));
+ IV2 U319 ( .A(pi17), .Z(n187));
+ IV2 U320 ( .A(pi18), .Z(n178));
+ IV2 U321 ( .A(n273), .Z(n172));
+ OR2 U322 ( .A(pi20), .B(n168), .Z(n273));
+ AN2 U323 ( .A(n290), .B(n252), .Z(po00));
+ IV2 U324 ( .A(pi21), .Z(n252));
+ OR2 U325 ( .A(n256), .B(n291), .Z(n290));
+ OR2 U326 ( .A(n257), .B(n292), .Z(n291));
+ AN2 U327 ( .A(pi03), .B(n258), .Z(n292));
+ AN2 U328 ( .A(n284), .B(pi20), .Z(n258));
+ AN2 U329 ( .A(n184), .B(n168), .Z(n257));
+ IV2 U330 ( .A(pi19), .Z(n168));
+ IV2 U331 ( .A(pi20), .Z(n184));
+ AN2 U332 ( .A(n293), .B(pi17), .Z(n256));
+ IV2 U333 ( .A(n284), .Z(n293));
+ OR2 U334 ( .A(pi18), .B(pi19), .Z(n284));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/ttt2.ys b/examples/smtbmc/glift/ttt2.ys
new file mode 100644
index 000000000..1314d4975
--- /dev/null
+++ b/examples/smtbmc/glift/ttt2.ys
@@ -0,0 +1,41 @@
+read_verilog ttt2.v
+techmap
+flatten
+select ttt2_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename ttt2_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog ttt2.v
+techmap
+flatten
+select ttt2_lev2
+glift -create-precise-model
+techmap
+opt
+rename ttt2_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution ttt2.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file ttt2.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/examples/smtbmc/glift/x1.v b/examples/smtbmc/glift/x1.v
new file mode 100755
index 000000000..39b5284d3
--- /dev/null
+++ b/examples/smtbmc/glift/x1.v
@@ -0,0 +1,380 @@
+module x1_lev2(pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23, pi24, pi25, pi26, pi27, pi28, pi29,
+ pi30, pi31, pi32, pi33, pi34, pi35, pi36, pi37, pi38, pi39,
+ pi40, pi41, pi42, pi43, pi44, pi45, pi46, pi47, pi48, pi49,
+ pi50, po00, po01, po02, po03, po04, po05, po06, po07, po08,
+ po09, po10, po11, po12, po13, po14, po15, po16, po17, po18,
+ po19, po20, po21, po22, po23, po24, po25, po26, po27, po28,
+ po29, po30, po31, po32, po33, po34);
+
+input pi00, pi01, pi02, pi03, pi04, pi05, pi06, pi07, pi08, pi09,
+ pi10, pi11, pi12, pi13, pi14, pi15, pi16, pi17, pi18, pi19,
+ pi20, pi21, pi22, pi23, pi24, pi25, pi26, pi27, pi28, pi29,
+ pi30, pi31, pi32, pi33, pi34, pi35, pi36, pi37, pi38, pi39,
+ pi40, pi41, pi42, pi43, pi44, pi45, pi46, pi47, pi48, pi49,
+ pi50;
+
+output po00, po01, po02, po03, po04, po05, po06, po07, po08, po09,
+ po10, po11, po12, po13, po14, po15, po16, po17, po18, po19,
+ po20, po21, po22, po23, po24, po25, po26, po27, po28, po29,
+ po30, po31, po32, po33, po34;
+
+wire po05, po16, po18, po24, po25, po28, po29, n270, n271, n272,
+ n273, n274, n275, n276, n277, n278, n279, n280, n281, n282,
+ n283, n284, n285, n286, n287, n288, n289, n290, n291, n292,
+ n293, n294, n295, n296, n297, n298, n299, n300, n301, n302,
+ n303, n304, n305, n306, n307, n308, n309, n310, n311, n312,
+ n313, n314, n315, n316, n317, n318, n319, n320, n321, n322,
+ n323, n324, n325, n326, n327, n328, n329, n330, n331, n332,
+ n333, n334, n335, n336, n337, n338, n339, n340, n341, n342,
+ n343, n344, n345, n346, n347, n348, n349, n350, n351, n352,
+ n353, n354, n355, n356, n357, n358, n359, n360, n361, n362,
+ n363, n364, n365, n366, n367, n368, n369, n370, n371, n372,
+ n373, n374, n375, n376, n377, n378, n379, n380, n381, n382,
+ n383, n384, n385, n386, n387, n388, n389, n390, n391, n392,
+ n393, n394, n395, n396, n397, n398, n399, n400, n401, n402,
+ n403, n404, n405, n406, n407, n408, n409, n410, n411, n412,
+ n413, n414, n415, n416, n417, n418, n419, n420, n421, n422,
+ n423, n424, n425, n426, n427, n428, n429, n430, n431, n432,
+ n433, n434, n435, n436, n437, n438, n439, n440, n441, n442,
+ n443, n444, n445, n446, n447, n448, n449, n450, n451, n452,
+ n453, n454, n455, n456, n457, n458, n459, n460, n461, n462,
+ n463, n464, n465, n466, n467, n468, n469, n470, n471, n472,
+ n473, n474, n475, n476, n477, n478, n479, n480, n481, n482,
+ n483, n484, n485, n486, n487, n488, n489, n490, n491, n492,
+ n493, n494, n495, n496, n497, n498, n499, n500, n501, n502,
+ n503, n504, n505, n506, n507, n508, n509, n510, n511, n512,
+ n513, n514, n515, n516, n517, n518, n519, n520, n521, n522,
+ n523, n524, n525, n526, n527, n528, n529, n530, n531, n532,
+ n533;
+
+assign po05 = pi32;
+
+assign po16 = pi37;
+
+assign po18 = pi38;
+
+assign po24 = pi23;
+
+assign po25 = pi24;
+
+assign po28 = pi48;
+
+assign po29 = pi49;
+
+ IV2 U294 ( .A(po32), .Z(po33));
+ OR2 U295 ( .A(n270), .B(n271), .Z(po32));
+ OR2 U296 ( .A(po25), .B(po05), .Z(n271));
+ AN2 U297 ( .A(n272), .B(n273), .Z(n270));
+ OR2 U298 ( .A(pi31), .B(po01), .Z(n273));
+ AN2 U299 ( .A(n274), .B(pi18), .Z(po31));
+ AN2 U300 ( .A(pi17), .B(n275), .Z(n274));
+ AN2 U301 ( .A(n276), .B(n272), .Z(po30));
+ OR2 U302 ( .A(n277), .B(n278), .Z(n276));
+ AN2 U303 ( .A(n279), .B(n280), .Z(n278));
+ OR2 U304 ( .A(n281), .B(pi31), .Z(n280));
+ AN2 U305 ( .A(pi35), .B(n282), .Z(n281));
+ AN2 U306 ( .A(n283), .B(n284), .Z(n277));
+ OR2 U307 ( .A(n285), .B(n286), .Z(n284));
+ AN2 U308 ( .A(pi31), .B(n287), .Z(n286));
+ IV2 U309 ( .A(pi05), .Z(n287));
+ AN2 U310 ( .A(n288), .B(pi35), .Z(n285));
+ AN2 U311 ( .A(pi21), .B(pi13), .Z(n288));
+ AN2 U312 ( .A(pi07), .B(n289), .Z(po27));
+ OR2 U313 ( .A(n290), .B(n291), .Z(po26));
+ OR2 U314 ( .A(n292), .B(n293), .Z(n291));
+ AN2 U315 ( .A(n294), .B(n295), .Z(n293));
+ AN2 U316 ( .A(n296), .B(n297), .Z(n295));
+ AN2 U317 ( .A(pi33), .B(n298), .Z(n294));
+ IV2 U318 ( .A(n299), .Z(n298));
+ AN2 U319 ( .A(pi19), .B(pi00), .Z(n299));
+ AN2 U320 ( .A(n300), .B(n301), .Z(n292));
+ AN2 U321 ( .A(n302), .B(n303), .Z(n301));
+ OR2 U322 ( .A(n304), .B(pi35), .Z(n303));
+ AN2 U323 ( .A(n305), .B(pi25), .Z(n304));
+ AN2 U324 ( .A(pi11), .B(n306), .Z(n305));
+ AN2 U325 ( .A(n272), .B(n307), .Z(n302));
+ AN2 U326 ( .A(n308), .B(pi01), .Z(n300));
+ AN2 U327 ( .A(n279), .B(pi17), .Z(n308));
+ AN2 U328 ( .A(pi34), .B(n309), .Z(n290));
+ OR2 U329 ( .A(n310), .B(n311), .Z(po23));
+ AN2 U330 ( .A(n312), .B(n313), .Z(n310));
+ OR2 U331 ( .A(n314), .B(n315), .Z(po22));
+ AN2 U332 ( .A(n316), .B(n317), .Z(n315));
+ AN2 U333 ( .A(n318), .B(n319), .Z(n317));
+ OR2 U334 ( .A(n320), .B(n272), .Z(n319));
+ AN2 U335 ( .A(n321), .B(n322), .Z(n320));
+ IV2 U336 ( .A(pi02), .Z(n322));
+ AN2 U337 ( .A(n296), .B(n323), .Z(n321));
+ OR2 U338 ( .A(pi09), .B(n324), .Z(n318));
+ AN2 U339 ( .A(pi05), .B(pi21), .Z(n324));
+ AN2 U340 ( .A(pi31), .B(n309), .Z(n316));
+ AN2 U341 ( .A(n325), .B(n326), .Z(n314));
+ AN2 U342 ( .A(n283), .B(n327), .Z(n325));
+ OR2 U343 ( .A(n328), .B(n329), .Z(n327));
+ OR2 U344 ( .A(n330), .B(n331), .Z(n329));
+ OR2 U345 ( .A(n332), .B(n333), .Z(n331));
+ AN2 U346 ( .A(po05), .B(n272), .Z(n333));
+ AN2 U347 ( .A(pi43), .B(n296), .Z(n332));
+ AN2 U348 ( .A(pi47), .B(pi39), .Z(n330));
+ OR2 U349 ( .A(n334), .B(n335), .Z(n328));
+ OR2 U350 ( .A(n336), .B(n337), .Z(n335));
+ AN2 U351 ( .A(n338), .B(pi40), .Z(n337));
+ AN2 U352 ( .A(n339), .B(n340), .Z(n338));
+ AN2 U353 ( .A(n341), .B(n342), .Z(n336));
+ AN2 U354 ( .A(n343), .B(n344), .Z(n342));
+ AN2 U355 ( .A(n345), .B(pi41), .Z(n341));
+ AN2 U356 ( .A(pi29), .B(n346), .Z(n334));
+ OR2 U357 ( .A(n347), .B(n348), .Z(po21));
+ AN2 U358 ( .A(pi09), .B(po05), .Z(n348));
+ AN2 U359 ( .A(n349), .B(n350), .Z(n347));
+ AN2 U360 ( .A(n346), .B(n279), .Z(n350));
+ AN2 U361 ( .A(n351), .B(n326), .Z(n349));
+ OR2 U362 ( .A(n352), .B(n353), .Z(po20));
+ OR2 U363 ( .A(n354), .B(n355), .Z(n353));
+ AN2 U364 ( .A(pi22), .B(po05), .Z(n355));
+ AN2 U365 ( .A(n356), .B(n357), .Z(n354));
+ OR2 U366 ( .A(n358), .B(n359), .Z(n356));
+ OR2 U367 ( .A(po05), .B(n360), .Z(n359));
+ AN2 U368 ( .A(n361), .B(n362), .Z(n360));
+ OR2 U369 ( .A(n363), .B(n364), .Z(n362));
+ AN2 U370 ( .A(n346), .B(n365), .Z(n364));
+ AN2 U371 ( .A(n366), .B(pi14), .Z(n346));
+ AN2 U372 ( .A(n367), .B(n343), .Z(n363));
+ OR2 U373 ( .A(n368), .B(n365), .Z(n367));
+ OR2 U374 ( .A(n351), .B(pi29), .Z(n365));
+ AN2 U375 ( .A(pi28), .B(n345), .Z(n368));
+ AN2 U376 ( .A(n309), .B(n369), .Z(n361));
+ AN2 U377 ( .A(pi07), .B(n370), .Z(n358));
+ OR2 U378 ( .A(pi28), .B(pi29), .Z(n370));
+ OR2 U379 ( .A(n371), .B(n372), .Z(n352));
+ AN2 U380 ( .A(pi01), .B(n373), .Z(n372));
+ OR2 U381 ( .A(n374), .B(pi30), .Z(n373));
+ AN2 U382 ( .A(pi10), .B(pi25), .Z(n374));
+ AN2 U383 ( .A(n375), .B(n376), .Z(n371));
+ OR2 U384 ( .A(pi40), .B(pi41), .Z(n376));
+ OR2 U385 ( .A(n377), .B(n378), .Z(po19));
+ OR2 U386 ( .A(n379), .B(n380), .Z(n378));
+ AN2 U387 ( .A(pi42), .B(pi01), .Z(n380));
+ AN2 U388 ( .A(pi12), .B(n381), .Z(n379));
+ OR2 U389 ( .A(n382), .B(n383), .Z(n381));
+ OR2 U390 ( .A(n384), .B(n385), .Z(n383));
+ AN2 U391 ( .A(n386), .B(n369), .Z(n384));
+ OR2 U392 ( .A(po34), .B(n387), .Z(n386));
+ OR2 U393 ( .A(pi40), .B(pi26), .Z(n387));
+ OR2 U394 ( .A(pi27), .B(pi28), .Z(po34));
+ OR2 U395 ( .A(pi31), .B(pi29), .Z(n382));
+ OR2 U396 ( .A(n388), .B(n389), .Z(n377));
+ OR2 U397 ( .A(n390), .B(n391), .Z(n389));
+ AN2 U398 ( .A(n392), .B(pi18), .Z(n391));
+ AN2 U399 ( .A(pi17), .B(n393), .Z(n392));
+ OR2 U400 ( .A(pi36), .B(pi40), .Z(n393));
+ AN2 U401 ( .A(n394), .B(pi22), .Z(n390));
+ AN2 U402 ( .A(n351), .B(n369), .Z(n394));
+ AN2 U403 ( .A(pi00), .B(n395), .Z(n388));
+ OR2 U404 ( .A(n396), .B(n397), .Z(n395));
+ OR2 U405 ( .A(n385), .B(n398), .Z(n397));
+ OR2 U406 ( .A(n399), .B(n400), .Z(n398));
+ AN2 U407 ( .A(pi31), .B(n272), .Z(n399));
+ OR2 U408 ( .A(n401), .B(n402), .Z(n385));
+ OR2 U409 ( .A(pi41), .B(pi35), .Z(n402));
+ OR2 U410 ( .A(po05), .B(pi43), .Z(n401));
+ OR2 U411 ( .A(n403), .B(n404), .Z(n396));
+ OR2 U412 ( .A(pi25), .B(n289), .Z(n404));
+ OR2 U413 ( .A(pi34), .B(pi28), .Z(n403));
+ IV2 U414 ( .A(po17), .Z(po15));
+ OR2 U415 ( .A(n405), .B(n406), .Z(po17));
+ OR2 U416 ( .A(n407), .B(n408), .Z(n406));
+ OR2 U417 ( .A(n409), .B(n410), .Z(n408));
+ AN2 U418 ( .A(pi28), .B(n411), .Z(n410));
+ OR2 U419 ( .A(pi03), .B(n296), .Z(n411));
+ AN2 U420 ( .A(n412), .B(n413), .Z(n409));
+ OR2 U421 ( .A(n414), .B(n415), .Z(n413));
+ AN2 U422 ( .A(pi02), .B(pi31), .Z(n415));
+ AN2 U423 ( .A(n416), .B(n417), .Z(n414));
+ AN2 U424 ( .A(n418), .B(n309), .Z(n416));
+ OR2 U425 ( .A(pi25), .B(n272), .Z(n418));
+ OR2 U426 ( .A(pi09), .B(n419), .Z(n412));
+ AN2 U427 ( .A(n420), .B(n421), .Z(n419));
+ AN2 U428 ( .A(n275), .B(n309), .Z(n421));
+ OR2 U429 ( .A(pi25), .B(pi35), .Z(n275));
+ AN2 U430 ( .A(n417), .B(pi21), .Z(n420));
+ OR2 U431 ( .A(pi26), .B(n313), .Z(n407));
+ AN2 U432 ( .A(pi33), .B(pi08), .Z(n313));
+ OR2 U433 ( .A(n422), .B(n423), .Z(n405));
+ OR2 U434 ( .A(po05), .B(pi27), .Z(n423));
+ AN2 U435 ( .A(n424), .B(n425), .Z(po14));
+ AN2 U436 ( .A(n426), .B(n309), .Z(n425));
+ OR2 U437 ( .A(n427), .B(n428), .Z(n426));
+ OR2 U438 ( .A(n429), .B(n430), .Z(n428));
+ AN2 U439 ( .A(pi29), .B(n431), .Z(n430));
+ OR2 U440 ( .A(pi43), .B(pi40), .Z(n427));
+ AN2 U441 ( .A(n326), .B(pi07), .Z(n424));
+ OR2 U442 ( .A(n432), .B(n433), .Z(po12));
+ OR2 U443 ( .A(n434), .B(n435), .Z(n433));
+ AN2 U444 ( .A(pi28), .B(n436), .Z(n435));
+ OR2 U445 ( .A(n437), .B(pi21), .Z(n436));
+ AN2 U446 ( .A(n438), .B(pi14), .Z(n437));
+ AN2 U447 ( .A(n439), .B(n323), .Z(n438));
+ OR2 U448 ( .A(n440), .B(n441), .Z(n439));
+ IV2 U449 ( .A(n442), .Z(n441));
+ AN2 U450 ( .A(n443), .B(pi15), .Z(n440));
+ AN2 U451 ( .A(n444), .B(n445), .Z(n434));
+ AN2 U452 ( .A(n446), .B(n312), .Z(n445));
+ AN2 U453 ( .A(n447), .B(n448), .Z(n446));
+ OR2 U454 ( .A(n282), .B(n307), .Z(n447));
+ IV2 U455 ( .A(pi18), .Z(n307));
+ AN2 U456 ( .A(n449), .B(pi40), .Z(n444));
+ AN2 U457 ( .A(n450), .B(n451), .Z(n449));
+ OR2 U458 ( .A(n339), .B(n297), .Z(n451));
+ IV2 U459 ( .A(n452), .Z(n450));
+ AN2 U460 ( .A(n453), .B(n339), .Z(n452));
+ OR2 U461 ( .A(n340), .B(pi12), .Z(n453));
+ AN2 U462 ( .A(pi02), .B(pi03), .Z(n340));
+ AN2 U463 ( .A(pi46), .B(pi39), .Z(n432));
+ IV2 U464 ( .A(po13), .Z(po11));
+ OR2 U465 ( .A(n454), .B(n455), .Z(po13));
+ OR2 U466 ( .A(n456), .B(n457), .Z(n455));
+ AN2 U467 ( .A(pi25), .B(n458), .Z(n457));
+ OR2 U468 ( .A(n459), .B(n460), .Z(n458));
+ OR2 U469 ( .A(n461), .B(n462), .Z(n460));
+ AN2 U470 ( .A(n463), .B(n464), .Z(n461));
+ OR2 U471 ( .A(n282), .B(n465), .Z(n464));
+ OR2 U472 ( .A(pi12), .B(pi09), .Z(n465));
+ IV2 U473 ( .A(pi50), .Z(n463));
+ AN2 U474 ( .A(pi07), .B(n466), .Z(n456));
+ OR2 U475 ( .A(n467), .B(n468), .Z(n466));
+ OR2 U476 ( .A(n469), .B(n429), .Z(n468));
+ AN2 U477 ( .A(pi28), .B(n470), .Z(n429));
+ AN2 U478 ( .A(n400), .B(n471), .Z(n469));
+ OR2 U479 ( .A(pi40), .B(n431), .Z(n471));
+ OR2 U480 ( .A(pi43), .B(n289), .Z(n467));
+ AN2 U481 ( .A(pi19), .B(pi33), .Z(n289));
+ OR2 U482 ( .A(po01), .B(n472), .Z(n454));
+ OR2 U483 ( .A(po28), .B(po16), .Z(n472));
+ OR2 U484 ( .A(n473), .B(n474), .Z(po10));
+ AN2 U485 ( .A(n475), .B(pi41), .Z(n474));
+ AN2 U486 ( .A(n476), .B(n477), .Z(n475));
+ OR2 U487 ( .A(n297), .B(n343), .Z(n476));
+ AN2 U488 ( .A(n478), .B(n479), .Z(n473));
+ AN2 U489 ( .A(n283), .B(n296), .Z(n479));
+ AN2 U490 ( .A(pi29), .B(n345), .Z(n478));
+ IV2 U491 ( .A(n480), .Z(n345));
+ IV2 U492 ( .A(po07), .Z(po09));
+ OR2 U493 ( .A(n481), .B(n482), .Z(po08));
+ AN2 U494 ( .A(pi45), .B(pi39), .Z(n482));
+ AN2 U495 ( .A(n483), .B(n484), .Z(n481));
+ OR2 U496 ( .A(n485), .B(n486), .Z(n484));
+ AN2 U497 ( .A(pi29), .B(n312), .Z(n486));
+ AN2 U498 ( .A(n296), .B(n309), .Z(n312));
+ AN2 U499 ( .A(n351), .B(n487), .Z(n485));
+ OR2 U500 ( .A(n488), .B(n326), .Z(n487));
+ AN2 U501 ( .A(pi06), .B(n357), .Z(n488));
+ AN2 U502 ( .A(pi03), .B(pi28), .Z(n351));
+ AN2 U503 ( .A(n323), .B(n431), .Z(n483));
+ OR2 U504 ( .A(n489), .B(n490), .Z(po07));
+ OR2 U505 ( .A(pi33), .B(n311), .Z(n490));
+ IV2 U506 ( .A(n491), .Z(n311));
+ OR2 U507 ( .A(n492), .B(n493), .Z(n491));
+ OR2 U508 ( .A(n494), .B(n297), .Z(n493));
+ IV2 U509 ( .A(pi08), .Z(n297));
+ AN2 U510 ( .A(n375), .B(n369), .Z(n494));
+ IV2 U511 ( .A(n448), .Z(n375));
+ OR2 U512 ( .A(n477), .B(n366), .Z(n448));
+ OR2 U513 ( .A(n431), .B(n344), .Z(n477));
+ IV2 U514 ( .A(pi16), .Z(n344));
+ OR2 U515 ( .A(n495), .B(n496), .Z(n492));
+ OR2 U516 ( .A(pi00), .B(n339), .Z(n496));
+ AN2 U517 ( .A(n369), .B(n343), .Z(n339));
+ IV2 U518 ( .A(n497), .Z(n495));
+ OR2 U519 ( .A(n498), .B(pi40), .Z(n497));
+ AN2 U520 ( .A(n369), .B(pi41), .Z(n498));
+ OR2 U521 ( .A(po05), .B(n422), .Z(n489));
+ OR2 U522 ( .A(po25), .B(po24), .Z(n422));
+ OR2 U523 ( .A(n499), .B(n500), .Z(po06));
+ AN2 U524 ( .A(pi27), .B(n501), .Z(n500));
+ AN2 U525 ( .A(n502), .B(n503), .Z(n499));
+ AN2 U526 ( .A(n504), .B(n480), .Z(n503));
+ OR2 U527 ( .A(n431), .B(n366), .Z(n480));
+ IV2 U528 ( .A(pi14), .Z(n431));
+ AN2 U529 ( .A(n470), .B(n296), .Z(n504));
+ IV2 U530 ( .A(pi07), .Z(n296));
+ IV2 U531 ( .A(pi03), .Z(n470));
+ AN2 U532 ( .A(pi28), .B(n279), .Z(n502));
+ AN2 U533 ( .A(pi26), .B(n501), .Z(po04));
+ OR2 U534 ( .A(pi21), .B(n323), .Z(n501));
+ AN2 U535 ( .A(n505), .B(n506), .Z(po03));
+ AN2 U536 ( .A(n507), .B(n279), .Z(n506));
+ AN2 U537 ( .A(n369), .B(n283), .Z(n279));
+ IV2 U538 ( .A(pi21), .Z(n369));
+ AN2 U539 ( .A(n442), .B(n400), .Z(n507));
+ OR2 U540 ( .A(pi29), .B(pi40), .Z(n400));
+ OR2 U541 ( .A(n366), .B(n343), .Z(n442));
+ IV2 U542 ( .A(pi06), .Z(n343));
+ IV2 U543 ( .A(pi15), .Z(n366));
+ AN2 U544 ( .A(n326), .B(pi14), .Z(n505));
+ AN2 U545 ( .A(n508), .B(n443), .Z(n326));
+ IV2 U546 ( .A(n357), .Z(n443));
+ OR2 U547 ( .A(pi04), .B(pi20), .Z(n357));
+ OR2 U548 ( .A(n509), .B(n510), .Z(po02));
+ OR2 U549 ( .A(n511), .B(n512), .Z(n510));
+ AN2 U550 ( .A(pi44), .B(pi39), .Z(n512));
+ AN2 U551 ( .A(n513), .B(n514), .Z(n511));
+ AN2 U552 ( .A(n515), .B(n516), .Z(n514));
+ AN2 U553 ( .A(n309), .B(n306), .Z(n515));
+ IV2 U554 ( .A(pi10), .Z(n306));
+ AN2 U555 ( .A(n417), .B(pi25), .Z(n513));
+ IV2 U556 ( .A(n517), .Z(n417));
+ OR2 U557 ( .A(n518), .B(n519), .Z(n509));
+ AN2 U558 ( .A(n520), .B(pi09), .Z(n519));
+ AN2 U559 ( .A(n521), .B(pi02), .Z(n520));
+ AN2 U560 ( .A(pi31), .B(n508), .Z(n521));
+ IV2 U561 ( .A(pi22), .Z(n508));
+ AN2 U562 ( .A(n522), .B(n272), .Z(n518));
+ IV2 U563 ( .A(pi09), .Z(n272));
+ AN2 U564 ( .A(n523), .B(n524), .Z(n522));
+ AN2 U565 ( .A(n525), .B(pi35), .Z(n524));
+ AN2 U566 ( .A(pi21), .B(n526), .Z(n525));
+ IV2 U567 ( .A(pi13), .Z(n526));
+ AN2 U568 ( .A(pi01), .B(n283), .Z(n523));
+ AN2 U569 ( .A(n323), .B(n309), .Z(n283));
+ IV2 U570 ( .A(pi00), .Z(n309));
+ IV2 U571 ( .A(pi12), .Z(n323));
+ OR2 U572 ( .A(n527), .B(n528), .Z(po00));
+ AN2 U573 ( .A(po01), .B(n459), .Z(n528));
+ OR2 U574 ( .A(pi30), .B(pi42), .Z(po01));
+ AN2 U575 ( .A(pi25), .B(n529), .Z(n527));
+ OR2 U576 ( .A(n530), .B(n517), .Z(n529));
+ OR2 U577 ( .A(n531), .B(n532), .Z(n517));
+ OR2 U578 ( .A(n462), .B(n459), .Z(n532));
+ IV2 U579 ( .A(pi01), .Z(n459));
+ IV2 U580 ( .A(pi11), .Z(n462));
+ OR2 U581 ( .A(pi13), .B(pi12), .Z(n531));
+ AN2 U582 ( .A(n533), .B(n282), .Z(n530));
+ IV2 U583 ( .A(pi17), .Z(n282));
+ IV2 U584 ( .A(n516), .Z(n533));
+ OR2 U585 ( .A(pi09), .B(pi21), .Z(n516));
+
+endmodule
+
+module IV2(A, Z);
+ input A;
+ output Z;
+
+ assign Z = ~A;
+endmodule
+
+module AN2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A & B;
+endmodule
+
+module OR2(A, B, Z);
+ input A, B;
+ output Z;
+
+ assign Z = A | B;
+endmodule
diff --git a/examples/smtbmc/glift/x1.ys b/examples/smtbmc/glift/x1.ys
new file mode 100644
index 000000000..b588dea92
--- /dev/null
+++ b/examples/smtbmc/glift/x1.ys
@@ -0,0 +1,41 @@
+read_verilog x1.v
+techmap
+flatten
+select x1_lev2
+glift -create-instrumented-model
+techmap
+opt
+rename x1_lev2 uut
+cd ..
+delete [AIONX][NVXR]2
+read_verilog x1.v
+techmap
+flatten
+select x1_lev2
+glift -create-precise-model
+techmap
+opt
+rename x1_lev2 spec
+cd ..
+delete [AIONX][NVXR]2
+
+design -push-copy
+miter -equiv spec uut miter
+flatten
+delete uut spec
+techmap
+opt
+stat miter
+qbfsat -O2 -write-solution x1.soln -solver yices -timeout 3600 -nocleanup -assume-outputs -assume-negative-polarity miter
+design -pop
+stat
+
+copy uut solved
+qbfsat -specialize-from-file x1.soln solved
+opt solved
+miter -equiv spec solved satmiter
+flatten
+sat -prove trigger 0 satmiter
+delete satmiter
+stat
+shell
diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc
index 463c5965b..cb19b8413 100644
--- a/frontends/aiger/aigerparse.cc
+++ b/frontends/aiger/aigerparse.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/frontends/aiger/aigerparse.h b/frontends/aiger/aigerparse.h
index 251a24977..81b955947 100644
--- a/frontends/aiger/aigerparse.h
+++ b/frontends/aiger/aigerparse.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/frontends/ast/Makefile.inc b/frontends/ast/Makefile.inc
index 91d917c91..9e6eee1e8 100644
--- a/frontends/ast/Makefile.inc
+++ b/frontends/ast/Makefile.inc
@@ -3,4 +3,5 @@ OBJS += frontends/ast/ast.o
OBJS += frontends/ast/simplify.o
OBJS += frontends/ast/genrtlil.o
OBJS += frontends/ast/dpicall.o
+OBJS += frontends/ast/ast_binding.o
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 57552d86c..7be8ab565 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2018 Ruben Undheim <ruben.undheim@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -52,8 +52,10 @@ namespace AST_INTERNAL {
const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr = NULL;
RTLIL::SigSpec ignoreThisSignalsInInitial;
AstNode *current_always, *current_top_block, *current_block, *current_block_child;
- AstModule *current_module;
+ Module *current_module;
bool current_always_clocked;
+ dict<std::string, int> current_memwr_count;
+ dict<std::string, pool<int>> current_memwr_visible;
}
// convert node types to string
@@ -175,6 +177,7 @@ std::string AST::type2str(AstNodeType type)
X(AST_STRUCT)
X(AST_UNION)
X(AST_STRUCT_ITEM)
+ X(AST_BIND)
#undef X
default:
log_abort();
@@ -196,7 +199,7 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id)
// create new node (AstNode constructor)
// (the optional child arguments make it easier to create AST trees)
-AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *child3)
+AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *child3, AstNode *child4)
{
static unsigned int hashidx_count = 123456789;
hashidx_count = mkhash_xorshift(hashidx_count);
@@ -233,6 +236,8 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
children.push_back(child2);
if (child3)
children.push_back(child3);
+ if (child4)
+ children.push_back(child4);
}
// create a (deep recursive) copy of a node
@@ -317,6 +322,8 @@ void AstNode::dumpAst(FILE *f, std::string indent) const
fprintf(f, " reg");
if (is_signed)
fprintf(f, " signed");
+ if (is_unsized)
+ fprintf(f, " unsized");
if (basic_prep)
fprintf(f, " basic_prep");
if (lookahead)
@@ -847,7 +854,7 @@ RTLIL::Const AstNode::bitsAsConst(int width)
return bitsAsConst(width, is_signed);
}
-RTLIL::Const AstNode::asAttrConst()
+RTLIL::Const AstNode::asAttrConst() const
{
log_assert(type == AST_CONSTANT);
@@ -862,8 +869,17 @@ RTLIL::Const AstNode::asAttrConst()
return val;
}
-RTLIL::Const AstNode::asParaConst()
+RTLIL::Const AstNode::asParaConst() const
{
+ if (type == AST_REALVALUE)
+ {
+ AstNode *strnode = AstNode::mkconst_str(stringf("%f", realvalue));
+ RTLIL::Const val = strnode->asAttrConst();
+ val.flags |= RTLIL::CONST_FLAG_REAL;
+ delete strnode;
+ return val;
+ }
+
RTLIL::Const val = asAttrConst();
if (is_signed)
val.flags |= RTLIL::CONST_FLAG_SIGNED;
@@ -968,8 +984,15 @@ void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast)
obj->attributes[ID::src] = ast->loc_string();
}
-// create a new AstModule from an AST_MODULE AST node
-static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast = NULL, bool quiet = false)
+static bool param_has_no_default(const AstNode *param) {
+ const auto &children = param->children;
+ log_assert(param->type == AST_PARAMETER);
+ log_assert(children.size() <= 2);
+ return children.empty() ||
+ (children.size() == 1 && children[0]->type == AST_RANGE);
+}
+
+static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool defer, AstNode *original_ast = NULL, bool quiet = false)
{
log_assert(current_scope.empty());
log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE);
@@ -980,11 +1003,13 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
log("Generating RTLIL representation for module `%s'.\n", ast->str.c_str());
}
- current_module = new AstModule;
- current_module->ast = NULL;
- current_module->name = ast->str;
- set_src_attr(current_module, ast);
- current_module->set_bool_attribute(ID::cells_not_processed);
+ AstModule *module = new AstModule;
+ current_module = module;
+
+ module->ast = NULL;
+ module->name = ast->str;
+ set_src_attr(module, ast);
+ module->set_bool_attribute(ID::cells_not_processed);
current_ast_mod = ast;
AstNode *ast_before_simplify;
@@ -1006,6 +1031,10 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
if (!defer)
{
+ for (const AstNode *node : ast->children)
+ if (node->type == AST_PARAMETER && param_has_no_default(node))
+ log_file_error(node->filename, node->location.first_line, "Parameter `%s' has no default value and has not been overridden!\n", node->str.c_str());
+
bool blackbox_module = flag_lib;
if (!blackbox_module && !flag_noblackbox) {
@@ -1023,7 +1052,11 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
}
}
+ // simplify this module or interface using the current design as context
+ // for lookup up ports and wires within cells
+ set_simplify_design_context(design);
while (ast->simplify(!flag_noopt, false, false, 0, -1, false, false)) { }
+ set_simplify_design_context(nullptr);
if (flag_dump_ast2) {
log("Dumping AST after simplification:\n");
@@ -1120,7 +1153,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
log_file_error(ast->filename, ast->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
- current_module->attributes[attr.first] = attr.second->asAttrConst();
+ module->attributes[attr.first] = attr.second->asAttrConst();
}
for (size_t i = 0; i < ast->children.size(); i++) {
AstNode *node = ast->children[i];
@@ -1148,35 +1181,93 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
continue;
- current_module->attributes[attr.first] = attr.second->asAttrConst();
+ module->attributes[attr.first] = attr.second->asAttrConst();
}
+ for (const AstNode *node : ast->children)
+ if (node->type == AST_PARAMETER)
+ current_module->avail_parameters(node->str);
}
if (ast->type == AST_INTERFACE)
- current_module->set_bool_attribute(ID::is_interface);
- current_module->ast = ast_before_simplify;
- current_module->nolatches = flag_nolatches;
- current_module->nomeminit = flag_nomeminit;
- current_module->nomem2reg = flag_nomem2reg;
- current_module->mem2reg = flag_mem2reg;
- current_module->noblackbox = flag_noblackbox;
- current_module->lib = flag_lib;
- current_module->nowb = flag_nowb;
- current_module->noopt = flag_noopt;
- current_module->icells = flag_icells;
- current_module->pwires = flag_pwires;
- current_module->autowire = flag_autowire;
- current_module->fixup_ports();
+ module->set_bool_attribute(ID::is_interface);
+ module->ast = ast_before_simplify;
+ module->nolatches = flag_nolatches;
+ module->nomeminit = flag_nomeminit;
+ module->nomem2reg = flag_nomem2reg;
+ module->mem2reg = flag_mem2reg;
+ module->noblackbox = flag_noblackbox;
+ module->lib = flag_lib;
+ module->nowb = flag_nowb;
+ module->noopt = flag_noopt;
+ module->icells = flag_icells;
+ module->pwires = flag_pwires;
+ module->autowire = flag_autowire;
+ module->fixup_ports();
if (flag_dump_rtlil) {
log("Dumping generated RTLIL:\n");
- log_module(current_module);
+ log_module(module);
log("--- END OF RTLIL DUMP ---\n");
}
+ design->add(current_module);
return current_module;
}
+RTLIL::Module *
+AST_INTERNAL::process_and_replace_module(RTLIL::Design *design,
+ RTLIL::Module *old_module,
+ AstNode *new_ast,
+ AstNode *original_ast)
+{
+ // The old module will be deleted. Rename and mark for deletion, using
+ // a static counter to make sure we get a unique name.
+ static unsigned counter;
+ std::ostringstream new_name;
+ new_name << old_module->name.str()
+ << "_before_process_and_replace_module_"
+ << counter;
+ ++counter;
+
+ design->rename(old_module, new_name.str());
+ old_module->set_bool_attribute(ID::to_delete);
+
+ // Check if the module was the top module. If it was, we need to remove
+ // the top attribute and put it on the new module.
+ bool is_top = false;
+ if (old_module->get_bool_attribute(ID::initial_top)) {
+ old_module->attributes.erase(ID::initial_top);
+ is_top = true;
+ }
+
+ // Generate RTLIL from AST for the new module and add to the design:
+ RTLIL::Module* new_module = process_module(design, new_ast, false, original_ast);
+
+ if (is_top)
+ new_module->set_bool_attribute(ID::top);
+
+ return new_module;
+}
+
+// renames identifiers in tasks and functions within a package
+static void rename_in_package_stmts(AstNode *pkg)
+{
+ std::unordered_set<std::string> idents;
+ for (AstNode *item : pkg->children)
+ idents.insert(item->str);
+ std::function<void(AstNode*)> rename =
+ [&rename, &idents, pkg](AstNode *node) {
+ for (AstNode *child : node->children) {
+ if (idents.count(child->str))
+ child->str = pkg->str + "::" + child->str.substr(1);
+ rename(child);
+ }
+ };
+ for (AstNode *item : pkg->children)
+ if (item->type == AST_FUNCTION || item->type == AST_TASK)
+ rename(item);
+}
+
// 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 no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil,
bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool pwires, bool nooverwrite, bool overwrite, bool defer, bool autowire)
@@ -1202,12 +1293,12 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
flag_autowire = autowire;
log_assert(current_ast->type == AST_DESIGN);
- for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++)
+ for (AstNode *child : current_ast->children)
{
- if ((*it)->type == AST_MODULE || (*it)->type == AST_INTERFACE)
+ if (child->type == AST_MODULE || child->type == AST_INTERFACE)
{
for (auto n : design->verilog_globals)
- (*it)->children.push_back(n->clone());
+ child->children.push_back(n->clone());
// append nodes from previous packages using package-qualified names
for (auto &n : design->verilog_packages) {
@@ -1222,45 +1313,63 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
} else {
cloned_node->str = n->str + std::string("::") + cloned_node->str.substr(1);
}
- (*it)->children.push_back(cloned_node);
+ child->children.push_back(cloned_node);
}
}
- if (flag_icells && (*it)->str.compare(0, 2, "\\$") == 0)
- (*it)->str = (*it)->str.substr(1);
+ if (flag_icells && child->str.compare(0, 2, "\\$") == 0)
+ child->str = child->str.substr(1);
- if (defer)
- (*it)->str = "$abstract" + (*it)->str;
+ bool defer_local = defer;
+ if (!defer_local)
+ for (const AstNode *node : child->children)
+ if (node->type == AST_PARAMETER && param_has_no_default(node))
+ {
+ log("Deferring `%s' because it contains parameter(s) without defaults.\n", child->str.c_str());
+ defer_local = true;
+ break;
+ }
- if (design->has((*it)->str)) {
- RTLIL::Module *existing_mod = design->module((*it)->str);
+
+ if (defer_local)
+ child->str = "$abstract" + child->str;
+
+ if (design->has(child->str)) {
+ RTLIL::Module *existing_mod = design->module(child->str);
if (!nooverwrite && !overwrite && !existing_mod->get_blackbox_attribute()) {
- log_file_error((*it)->filename, (*it)->location.first_line, "Re-definition of module `%s'!\n", (*it)->str.c_str());
+ log_file_error(child->filename, child->location.first_line, "Re-definition of module `%s'!\n", child->str.c_str());
} else if (nooverwrite) {
log("Ignoring re-definition of module `%s' at %s.\n",
- (*it)->str.c_str(), (*it)->loc_string().c_str());
+ child->str.c_str(), child->loc_string().c_str());
continue;
} else {
log("Replacing existing%s module `%s' at %s.\n",
existing_mod->get_bool_attribute(ID::blackbox) ? " blackbox" : "",
- (*it)->str.c_str(), (*it)->loc_string().c_str());
+ child->str.c_str(), child->loc_string().c_str());
design->remove(existing_mod);
}
}
- design->add(process_module(*it, defer));
+ process_module(design, child, defer_local);
current_ast_mod = nullptr;
}
- else if ((*it)->type == AST_PACKAGE) {
+ else if (child->type == AST_PACKAGE) {
// process enum/other declarations
- (*it)->simplify(true, false, false, 1, -1, false, false);
- design->verilog_packages.push_back((*it)->clone());
+ child->simplify(true, false, false, 1, -1, false, false);
+ rename_in_package_stmts(child);
+ design->verilog_packages.push_back(child->clone());
current_scope.clear();
}
+ else if (child->type == AST_BIND) {
+ // top-level bind construct
+ for (RTLIL::Binding *binding : child->genBindings())
+ design->add(binding);
+ }
else {
// must be global definition
- (*it)->simplify(false, false, false, 1, -1, false, false); //process enum/other declarations
- design->verilog_globals.push_back((*it)->clone());
+ if (child->type == AST_PARAMETER)
+ child->type = AST_LOCALPARAM; // cannot be overridden
+ design->verilog_globals.push_back(child->clone());
current_scope.clear();
}
}
@@ -1351,13 +1460,32 @@ void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule
}
}
+// AstModules may contain cells marked with ID::reprocess_after, which indicates
+// that it should be reprocessed once the specified module has been elaborated.
+bool AstModule::reprocess_if_necessary(RTLIL::Design *design)
+{
+ for (const RTLIL::Cell *cell : cells())
+ {
+ std::string modname = cell->get_string_attribute(ID::reprocess_after);
+ if (modname.empty())
+ continue;
+ if (design->module(modname) || design->module("$abstract" + modname)) {
+ log("Reprocessing module %s because instantiated module %s has become available.\n",
+ log_id(name), log_id(modname));
+ loadconfig();
+ process_and_replace_module(design, this, ast, NULL);
+ return true;
+ }
+ }
+ return false;
+}
+
// When an interface instance is found in a module, the whole RTLIL for the module will be rederived again
// from AST. The interface members are copied into the AST module with the prefix of the interface.
-void AstModule::reprocess_module(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module*> &local_interfaces)
+void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module*> &local_interfaces)
{
loadconfig();
- bool is_top = false;
AstNode *new_ast = ast->clone();
for (auto &intf : local_interfaces) {
std::string intfname = intf.first.str();
@@ -1414,29 +1542,15 @@ void AstModule::reprocess_module(RTLIL::Design *design, const dict<RTLIL::IdStri
}
}
- // The old module will be deleted. Rename and mark for deletion:
- std::string original_name = this->name.str();
- std::string changed_name = original_name + "_before_replacing_local_interfaces";
- design->rename(this, changed_name);
- this->set_bool_attribute(ID::to_delete);
+ // Generate RTLIL from AST for the new module and add to the design,
+ // renaming this module to move it out of the way.
+ RTLIL::Module* new_module =
+ process_and_replace_module(design, this, new_ast, ast_before_replacing_interface_ports);
- // Check if the module was the top module. If it was, we need to remove the top attribute and put it on the
- // new module.
- if (this->get_bool_attribute(ID::initial_top)) {
- this->attributes.erase(ID::initial_top);
- is_top = true;
- }
-
- // Generate RTLIL from AST for the new module and add to the design:
- AstModule *newmod = process_module(new_ast, false, ast_before_replacing_interface_ports);
- delete(new_ast);
- design->add(newmod);
- RTLIL::Module* mod = design->module(original_name);
- if (is_top)
- mod->set_bool_attribute(ID::top);
+ delete new_ast;
// Set the attribute "interfaces_replaced_in_module" so that it does not happen again.
- mod->set_bool_attribute(ID::interfaces_replaced_in_module);
+ new_module->set_bool_attribute(ID::interfaces_replaced_in_module);
}
// create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces
@@ -1486,7 +1600,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
explode_interface_port(new_ast, intfmodule, intfname, modport);
}
- design->add(process_module(new_ast, false));
+ process_module(design, new_ast, false);
design->module(modname)->check();
RTLIL::Module* mod = design->module(modname);
@@ -1537,7 +1651,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
if (!design->has(modname)) {
new_ast->str = modname;
- design->add(process_module(new_ast, false, NULL, quiet));
+ process_module(design, new_ast, false, NULL, quiet);
design->module(modname)->check();
} else if (!quiet) {
log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
@@ -1547,6 +1661,40 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
return modname;
}
+static std::string serialize_param_value(const RTLIL::Const &val) {
+ std::string res;
+ if (val.flags & RTLIL::ConstFlags::CONST_FLAG_STRING)
+ res.push_back('t');
+ if (val.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED)
+ res.push_back('s');
+ if (val.flags & RTLIL::ConstFlags::CONST_FLAG_REAL)
+ res.push_back('r');
+ res += stringf("%d", GetSize(val));
+ res.push_back('\'');
+ for (int i = GetSize(val) - 1; i >= 0; i--) {
+ switch (val.bits[i]) {
+ case RTLIL::State::S0: res.push_back('0'); break;
+ case RTLIL::State::S1: res.push_back('1'); break;
+ case RTLIL::State::Sx: res.push_back('x'); break;
+ case RTLIL::State::Sz: res.push_back('z'); break;
+ case RTLIL::State::Sa: res.push_back('?'); break;
+ case RTLIL::State::Sm: res.push_back('m'); break;
+ }
+ }
+ return res;
+}
+
+std::string AST::derived_module_name(std::string stripped_name, const std::vector<std::pair<RTLIL::IdString, RTLIL::Const>> &parameters) {
+ std::string para_info;
+ for (const auto &elem : parameters)
+ para_info += stringf("%s=%s", elem.first.c_str(), serialize_param_value(elem.second).c_str());
+
+ if (para_info.size() > 60)
+ return "$paramod$" + sha1(para_info) + stripped_name;
+ else
+ return "$paramod" + stripped_name + para_info;
+}
+
// create a new parametric module (when needed) and return the name of the generated module
std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, AstNode **new_ast_out, bool quiet)
{
@@ -1555,9 +1703,8 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
if (stripped_name.compare(0, 9, "$abstract") == 0)
stripped_name = stripped_name.substr(9);
- std::string para_info;
-
int para_counter = 0;
+ std::vector<std::pair<RTLIL::IdString, RTLIL::Const>> named_parameters;
for (const auto child : ast->children) {
if (child->type != AST_PARAMETER)
continue;
@@ -1566,25 +1713,21 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
if (it != parameters.end()) {
if (!quiet)
log("Parameter %s = %s\n", child->str.c_str(), log_signal(it->second));
- para_info += stringf("%s=%s", child->str.c_str(), log_signal(it->second));
+ named_parameters.emplace_back(child->str, it->second);
continue;
}
it = parameters.find(stringf("$%d", para_counter));
if (it != parameters.end()) {
if (!quiet)
log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(it->second));
- para_info += stringf("%s=%s", child->str.c_str(), log_signal(it->second));
+ named_parameters.emplace_back(child->str, it->second);
continue;
}
}
- std::string modname;
- if (parameters.size() == 0)
- modname = stripped_name;
- else if (para_info.size() > 60)
- modname = "$paramod$" + sha1(para_info) + stripped_name;
- else
- modname = "$paramod" + stripped_name + para_info;
+ std::string modname = stripped_name;
+ if (parameters.size()) // not named_parameters to cover hierarchical defparams
+ modname = derived_module_name(stripped_name, named_parameters);
if (design->has(modname))
return modname;
@@ -1619,6 +1762,8 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
}
continue;
rewrite_parameter:
+ if (param_has_no_default(child))
+ child->children.insert(child->children.begin(), nullptr);
delete child->children.at(0);
if ((it->second.flags & RTLIL::CONST_FLAG_REAL) != 0) {
child->children[0] = new AstNode(AST_REALVALUE);
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index 1c9a6ee47..48ec9a063 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -1,7 +1,7 @@
/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -160,7 +160,8 @@ namespace AST
AST_TYPEDEF,
AST_STRUCT,
AST_UNION,
- AST_STRUCT_ITEM
+ AST_STRUCT_ITEM,
+ AST_BIND
};
struct AstSrcLocType {
@@ -220,7 +221,7 @@ namespace AST
AstSrcLocType location;
// creating and deleting nodes
- AstNode(AstNodeType type = AST_NONE, AstNode *child1 = NULL, AstNode *child2 = NULL, AstNode *child3 = NULL);
+ AstNode(AstNodeType type = AST_NONE, AstNode *child1 = nullptr, AstNode *child2 = nullptr, AstNode *child3 = nullptr, AstNode *child4 = nullptr);
AstNode *clone() const;
void cloneInto(AstNode *other) const;
void delete_children();
@@ -261,6 +262,7 @@ namespace AST
void mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &delnodes);
void meminfo(int &mem_width, int &mem_size, int &addr_bits);
bool detect_latch(const std::string &var);
+ const RTLIL::Module* lookup_cell_module();
// additional functionality for evaluating constant functions
struct varinfo_t {
@@ -283,6 +285,9 @@ namespace AST
void dumpAst(FILE *f, std::string indent) const;
void dumpVlog(FILE *f, std::string indent) const;
+ // Generate RTLIL for a bind construct
+ std::vector<RTLIL::Binding *> genBindings() const;
+
// used by genRTLIL() for detecting expression width and sign
void detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real = NULL);
void detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real = NULL);
@@ -291,7 +296,7 @@ namespace AST
// for expressions the resulting signal vector is returned
// all generated cell instances, etc. are written to the RTLIL::Module pointed to by AST_INTERNAL::current_module
RTLIL::SigSpec genRTLIL(int width_hint = -1, bool sign_hint = false);
- RTLIL::SigSpec genWidthRTLIL(int width, const dict<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr = NULL);
+ RTLIL::SigSpec genWidthRTLIL(int width, bool sgn, const dict<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr = NULL);
// compare AST nodes
bool operator==(const AstNode &other) const;
@@ -309,8 +314,8 @@ namespace AST
RTLIL::Const bitsAsConst(int width, bool is_signed);
RTLIL::Const bitsAsConst(int width = -1);
RTLIL::Const bitsAsUnsizedConst(int width);
- RTLIL::Const asAttrConst();
- RTLIL::Const asParaConst();
+ RTLIL::Const asAttrConst() const;
+ RTLIL::Const asParaConst() const;
uint64_t asInt(bool is_signed);
bool bits_only_01() const;
bool asBool() const;
@@ -326,6 +331,9 @@ namespace AST
// helpers for locations
std::string loc_string() const;
+
+ // Helper for looking up identifiers which are prefixed with the current module name
+ std::string try_pop_module_prefix() const;
};
// process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code
@@ -341,7 +349,8 @@ namespace AST
RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool mayfail) override;
RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail) override;
std::string derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, AstNode **new_ast_out, bool quiet = false);
- void reprocess_module(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces) override;
+ void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces) override;
+ bool reprocess_if_necessary(RTLIL::Design *design) override;
RTLIL::Module *clone() const override;
void loadconfig() const;
};
@@ -367,6 +376,17 @@ namespace AST
// Helper for setting the src attribute.
void set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast);
+
+ // struct helper exposed from simplify for genrtlil
+ AstNode *make_struct_member_range(AstNode *node, AstNode *member_node);
+
+ // generate standard $paramod... derived module name; parameters should be
+ // in the order they are declared in the instantiated module
+ std::string derived_module_name(std::string stripped_name, const std::vector<std::pair<RTLIL::IdString, RTLIL::Const>> &parameters);
+
+ // used to provide simplify() access to the current design for looking up
+ // modules, ports, wires, etc.
+ void set_simplify_design_context(const RTLIL::Design *design);
}
namespace AST_INTERNAL
@@ -379,10 +399,24 @@ namespace AST_INTERNAL
extern const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr;
extern RTLIL::SigSpec ignoreThisSignalsInInitial;
extern AST::AstNode *current_always, *current_top_block, *current_block, *current_block_child;
- extern AST::AstModule *current_module;
+ extern RTLIL::Module *current_module;
extern bool current_always_clocked;
+ extern dict<std::string, int> current_memwr_count;
+ extern dict<std::string, pool<int>> current_memwr_visible;
struct LookaheadRewriter;
struct ProcessGenerator;
+
+ // Create and add a new AstModule from new_ast, then use it to replace
+ // old_module in design, renaming old_module to move it out of the way.
+ // Return the new module.
+ //
+ // If original_ast is not null, it will be used as the AST node for the
+ // new module. Otherwise, new_ast will be used.
+ RTLIL::Module *
+ process_and_replace_module(RTLIL::Design *design,
+ RTLIL::Module *old_module,
+ AST::AstNode *new_ast,
+ AST::AstNode *original_ast = nullptr);
}
YOSYS_NAMESPACE_END
diff --git a/frontends/ast/ast_binding.cc b/frontends/ast/ast_binding.cc
new file mode 100644
index 000000000..c20d1df4d
--- /dev/null
+++ b/frontends/ast/ast_binding.cc
@@ -0,0 +1,49 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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 "ast_binding.h"
+#include "ast.h"
+
+YOSYS_NAMESPACE_BEGIN
+
+using namespace AST_INTERNAL;
+
+AST::Binding::Binding(RTLIL::IdString target_type,
+ RTLIL::IdString target_name,
+ const AstNode &cell)
+ : RTLIL::Binding(target_type, target_name),
+ ast_node(cell.clone())
+{
+ log_assert(cell.type == AST_CELL);
+}
+
+std::string
+AST::Binding::describe() const
+{
+ std::ostringstream oss;
+ oss << "directive to bind " << ast_node->str
+ << " to " << target_name.str();
+ if (!target_type.empty())
+ oss << " (target type: "
+ << target_type.str()
+ << ")";
+ return oss.str();
+}
+
+PRIVATE_NAMESPACE_END
diff --git a/frontends/ast/ast_binding.h b/frontends/ast/ast_binding.h
new file mode 100644
index 000000000..641497d52
--- /dev/null
+++ b/frontends/ast/ast_binding.h
@@ -0,0 +1,58 @@
+/* -*- c++ -*-
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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.
+ *
+ * ---
+ *
+ * This header declares the AST::Binding class
+ *
+ * This is used to support the bind directive and is to RTLIL::Binding as
+ * AST::AstModule is to RTLIL::Module, holding a syntax-level representation of
+ * cells until we get to a stage where they make sense. In the case of a bind
+ * directive, this is when we elaborate the design in the hierarchy pass.
+ *
+ */
+
+#ifndef AST_BINDING_H
+#define AST_BINDING_H
+
+#include "kernel/rtlil.h"
+#include "kernel/binding.h"
+
+#include <memory>
+
+YOSYS_NAMESPACE_BEGIN
+
+namespace AST
+{
+ class Binding : public RTLIL::Binding
+ {
+ public:
+ Binding(RTLIL::IdString target_type,
+ RTLIL::IdString target_name,
+ const AstNode &cell);
+
+ std::string describe() const override;
+
+ private:
+ // The syntax-level representation of the cell to be bound.
+ std::unique_ptr<AstNode> ast_node;
+ };
+}
+
+YOSYS_NAMESPACE_END
+
+#endif
diff --git a/frontends/ast/dpicall.cc b/frontends/ast/dpicall.cc
index 948c9083c..12a7e1183 100644
--- a/frontends/ast/dpicall.cc
+++ b/frontends/ast/dpicall.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc
index d4299bf69..4c25287ad 100644
--- a/frontends/ast/genrtlil.cc
+++ b/frontends/ast/genrtlil.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -28,8 +28,10 @@
#include "kernel/log.h"
#include "kernel/utils.h"
+#include "kernel/binding.h"
#include "libs/sha1/sha1.h"
#include "ast.h"
+#include "ast_binding.h"
#include <sstream>
#include <stdarg.h>
@@ -319,16 +321,14 @@ struct AST_INTERNAL::ProcessGenerator
LookaheadRewriter la_rewriter(always);
// generate process and simple root case
- proc = new RTLIL::Process;
+ proc = current_module->addProcess(stringf("$proc$%s:%d$%d", always->filename.c_str(), always->location.first_line, autoidx++));
set_src_attr(proc, always);
- proc->name = stringf("$proc$%s:%d$%d", always->filename.c_str(), always->location.first_line, autoidx++);
for (auto &attr : always->attributes) {
if (attr.second->type != AST_CONSTANT)
log_file_error(always->filename, always->location.first_line, "Attribute `%s' with non-constant value!\n",
attr.first.c_str());
proc->attributes[attr.first] = attr.second->asAttrConst();
}
- current_module->processes[proc->name] = proc;
current_case = &proc->root_case;
// create initial temporary signal for all output registers
@@ -399,6 +399,9 @@ struct AST_INTERNAL::ProcessGenerator
if (child->type == AST_BLOCK)
processAst(child);
+ for (auto sync: proc->syncs)
+ processMemWrites(sync);
+
if (initSyncSignals.size() > 0)
{
RTLIL::SyncRule *sync = new RTLIL::SyncRule;
@@ -563,7 +566,7 @@ struct AST_INTERNAL::ProcessGenerator
case AST_ASSIGN_LE:
{
RTLIL::SigSpec unmapped_lvalue = ast->children[0]->genRTLIL(), lvalue = unmapped_lvalue;
- RTLIL::SigSpec rvalue = ast->children[1]->genWidthRTLIL(lvalue.size(), &subst_rvalue_map.stdmap());
+ RTLIL::SigSpec rvalue = ast->children[1]->genWidthRTLIL(lvalue.size(), true, &subst_rvalue_map.stdmap());
pool<SigBit> lvalue_sigbits;
for (int i = 0; i < GetSize(lvalue); i++) {
@@ -590,9 +593,13 @@ struct AST_INTERNAL::ProcessGenerator
case AST_CASE:
{
+ int width_hint;
+ bool sign_hint;
+ ast->detectSignWidth(width_hint, sign_hint);
+
RTLIL::SwitchRule *sw = new RTLIL::SwitchRule;
set_src_attr(sw, ast);
- sw->signal = ast->children[0]->genWidthRTLIL(-1, &subst_rvalue_map.stdmap());
+ sw->signal = ast->children[0]->genWidthRTLIL(width_hint, sign_hint, &subst_rvalue_map.stdmap());
current_case->switches.push_back(sw);
for (auto &attr : ast->attributes) {
@@ -634,7 +641,7 @@ struct AST_INTERNAL::ProcessGenerator
else if (node->type == AST_BLOCK)
processAst(node);
else
- current_case->compare.push_back(node->genWidthRTLIL(sw->signal.size(), &subst_rvalue_map.stdmap()));
+ current_case->compare.push_back(node->genWidthRTLIL(width_hint, sign_hint, &subst_rvalue_map.stdmap()));
}
if (default_case != current_case)
sw->cases.push_back(current_case);
@@ -698,8 +705,99 @@ struct AST_INTERNAL::ProcessGenerator
log_abort();
}
}
+
+ void processMemWrites(RTLIL::SyncRule *sync)
+ {
+ // Maps per-memid AST_MEMWR IDs to indices in the mem_write_actions array.
+ dict<std::pair<std::string, int>, int> port_map;
+ for (auto child : always->children)
+ if (child->type == AST_MEMWR)
+ {
+ std::string memid = child->str;
+ int portid = child->children[3]->asInt(false);
+ int cur_idx = GetSize(sync->mem_write_actions);
+ RTLIL::MemWriteAction action;
+ set_src_attr(&action, child);
+ action.memid = memid;
+ action.address = child->children[0]->genWidthRTLIL(-1, true, &subst_rvalue_map.stdmap());
+ action.data = child->children[1]->genWidthRTLIL(current_module->memories[memid]->width, true, &subst_rvalue_map.stdmap());
+ action.enable = child->children[2]->genWidthRTLIL(-1, true, &subst_rvalue_map.stdmap());
+ RTLIL::Const orig_priority_mask = child->children[4]->bitsAsConst();
+ RTLIL::Const priority_mask = RTLIL::Const(0, cur_idx);
+ for (int i = 0; i < portid; i++) {
+ int new_bit = port_map[std::make_pair(memid, i)];
+ priority_mask.bits[new_bit] = orig_priority_mask.bits[i];
+ }
+ action.priority_mask = priority_mask;
+ sync->mem_write_actions.push_back(action);
+ port_map[std::make_pair(memid, portid)] = cur_idx;
+ }
+ }
};
+// Generate RTLIL for a bind construct
+//
+// The AST node will have one or more AST_IDENTIFIER children, which were added
+// by bind_target_instance in the parser. After these, it will have one or more
+// cells, as parsed by single_cell. These have type AST_CELL.
+//
+// If there is more than one AST_IDENTIFIER, the first one should be considered
+// a module identifier. If there is only one AST_IDENTIFIER, we can't tell at
+// this point whether it's a module/interface name or the name of an instance
+// because the correct interpretation depends on what's visible at elaboration
+// time. For now, we just treat it as a target instance with unknown type, and
+// we'll deal with the corner case in the hierarchy pass.
+//
+// To simplify downstream code, RTLIL::Binding only has a single target and
+// single bound instance. If we see the syntax that allows more than one of
+// either, we split it into multiple Binding objects.
+std::vector<RTLIL::Binding *> AstNode::genBindings() const
+{
+ // Partition children into identifiers and cells
+ int num_ids = 0;
+ for (int i = 0; i < GetSize(children); ++i) {
+ if (children[i]->type != AST_IDENTIFIER) {
+ log_assert(i > 0);
+ num_ids = i;
+ break;
+ }
+ }
+
+ // We should have found at least one child that's not an identifier
+ log_assert(num_ids > 0);
+
+ // Make sense of the identifiers, extracting a possible type name and a
+ // list of hierarchical IDs. We represent an unknown type with an empty
+ // string.
+ RTLIL::IdString tgt_type;
+ int first_tgt_inst = 0;
+ if (num_ids > 1) {
+ tgt_type = children[0]->str;
+ first_tgt_inst = 1;
+ }
+
+ std::vector<RTLIL::Binding *> ret;
+
+ // At this point, we know that children with index >= first_tgt_inst and
+ // index < num_ids are (hierarchical?) names of target instances. Make a
+ // binding object for each of them, and fill in the generated instance
+ // cells each time.
+ for (int i = first_tgt_inst; i < num_ids; ++i) {
+ const AstNode &tgt_child = *children[i];
+
+ for (int j = num_ids; j < GetSize(children); ++j) {
+ const AstNode &cell_child = *children[j];
+
+ log_assert(cell_child.type == AST_CELL);
+
+ ret.push_back(new AST::Binding(tgt_type, tgt_child.str,
+ cell_child));
+ }
+ }
+
+ return ret;
+}
+
// detect sign and width of an expression
void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real)
{
@@ -732,8 +830,15 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
case AST_IDENTIFIER:
id_ast = id2ast;
- if (id_ast == NULL && current_scope.count(str))
- id_ast = current_scope.at(str);
+ if (!id_ast) {
+ if (current_scope.count(str))
+ id_ast = current_scope[str];
+ else {
+ std::string alt = try_pop_module_prefix();
+ if (current_scope.count(alt))
+ id_ast = current_scope[alt];
+ }
+ }
if (!id_ast)
log_file_error(filename, location.first_line, "Failed to resolve identifier %s for width detection!\n", str.c_str());
if (id_ast->type == AST_PARAMETER || id_ast->type == AST_LOCALPARAM || id_ast->type == AST_ENUM_ITEM) {
@@ -772,6 +877,10 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1;
if (children.size() > 1)
range = children[1];
+ } else if (id_ast->type == AST_STRUCT_ITEM) {
+ AstNode *tmp_range = make_struct_member_range(this, id_ast);
+ this_width = tmp_range->range_left - tmp_range->range_right + 1;
+ delete tmp_range;
} else
log_file_error(filename, location.first_line, "Failed to detect width for identifier %s!\n", str.c_str());
if (range) {
@@ -823,7 +932,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (children.at(0)->type != AST_CONSTANT)
log_file_error(filename, location.first_line, "Static cast with non constant expression!\n");
children.at(1)->detectSignWidthWorker(width_hint, sign_hint);
- width_hint = children.at(0)->bitsAsConst().as_int();
+ this_width = children.at(0)->bitsAsConst().as_int();
+ width_hint = max(width_hint, this_width);
if (width_hint <= 0)
log_file_error(filename, location.first_line, "Static cast with zero or negative size!\n");
break;
@@ -923,6 +1033,40 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
width_hint = max(width_hint, this_width);
break;
+ case AST_CASE:
+ {
+ // This detects the _overall_ sign and width to be used for comparing
+ // the case expression with the case item expressions. The case
+ // expression and case item expressions are extended to the maximum
+ // width among them, and are only interpreted as signed if all of them
+ // are signed.
+ width_hint = -1;
+ sign_hint = true;
+ auto visit_case_expr = [&width_hint, &sign_hint] (AstNode *node) {
+ int sub_width_hint = -1;
+ bool sub_sign_hint = true;
+ node->detectSignWidth(sub_width_hint, sub_sign_hint);
+ width_hint = max(width_hint, sub_width_hint);
+ sign_hint &= sub_sign_hint;
+ };
+ visit_case_expr(children[0]);
+ for (size_t i = 1; i < children.size(); i++) {
+ AstNode *child = children[i];
+ for (AstNode *v : child->children)
+ if (v->type != AST_DEFAULT && v->type != AST_BLOCK)
+ visit_case_expr(v);
+ }
+ break;
+ }
+
+ case AST_PREFIX:
+ // Prefix nodes always resolve to identifiers in generate loops, so we
+ // can simply perform the resolution to determine the sign and width.
+ simplify(true, false, false, 1, -1, false, false);
+ log_assert(type == AST_IDENTIFIER);
+ detectSignWidthWorker(width_hint, sign_hint, found_real);
+ break;
+
case AST_FCALL:
if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq") {
if (GetSize(children) == 1) {
@@ -944,6 +1088,11 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
}
break;
}
+ if (str == "\\$size" || str == "\\$bits" || str == "\\$high" || str == "\\$low" || str == "\\$left" || str == "\\$right") {
+ width_hint = 32;
+ sign_hint = true;
+ break;
+ }
if (current_scope.count(str))
{
// This width detection is needed for function calls which are
@@ -983,8 +1132,9 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
// everything should have been handled above -> print error if not.
default:
+ AstNode *current_scope_ast = current_ast_mod == nullptr ? current_ast : current_ast_mod;
for (auto f : log_files)
- current_ast_mod->dumpAst(f, "verilog-ast> ");
+ current_scope_ast->dumpAst(f, "verilog-ast> ");
log_file_error(filename, location.first_line, "Don't know how to detect sign and width for %s node!\n", type2str(type).c_str());
}
@@ -1000,6 +1150,12 @@ void AstNode::detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real
if (found_real)
*found_real = false;
detectSignWidthWorker(width_hint, sign_hint, found_real);
+
+ constexpr int kWidthLimit = 1 << 24;
+ if (width_hint >= kWidthLimit)
+ log_file_error(filename, location.first_line,
+ "Expression width %d exceeds implementation limit of %d!\n",
+ width_hint, kWidthLimit);
}
static void check_unique_id(RTLIL::Module *module, RTLIL::IdString id,
@@ -1227,7 +1383,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
RTLIL::Wire *wire = current_module->addWire(str);
set_src_attr(wire, this);
wire->name = str;
- if (flag_autowire)
+
+ // If we are currently processing a bind directive which wires up
+ // signals or parameters explicitly, rather than with .*, then
+ // current_module will start out empty and we don't want to warn the
+ // user about it: we'll spot broken wiring later, when we run the
+ // hierarchy pass.
+ if (dynamic_cast<RTLIL::Binding*>(current_module)) {
+ /* nothing to do here */
+ } else if (flag_autowire)
log_file_warning(filename, location.first_line, "Identifier `%s' is implicitly declared.\n", str.c_str());
else
log_file_error(filename, location.first_line, "Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
@@ -1367,13 +1531,20 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// changing the size of signal can be done directly using RTLIL::SigSpec
case AST_CAST_SIZE: {
RTLIL::SigSpec size = children[0]->genRTLIL();
- RTLIL::SigSpec sig = children[1]->genRTLIL();
if (!size.is_fully_const())
log_file_error(filename, location.first_line, "Static cast with non constant expression!\n");
int width = size.as_int();
if (width <= 0)
log_file_error(filename, location.first_line, "Static cast with zero or negative size!\n");
- sig.extend_u0(width, sign_hint);
+ // determine the *signedness* of the expression
+ int sub_width_hint = -1;
+ bool sub_sign_hint = true;
+ children[1]->detectSignWidth(sub_width_hint, sub_sign_hint);
+ // generate the signal given the *cast's* size and the
+ // *expression's* signedness
+ RTLIL::SigSpec sig = children[1]->genWidthRTLIL(width, sub_sign_hint);
+ // context may effect this node's signedness, but not that of the
+ // casted expression
is_signed = sign_hint;
return sig;
}
@@ -1638,43 +1809,35 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
return RTLIL::SigSpec(wire);
}
- // generate $memwr cells for memory write ports
- case AST_MEMWR:
+ // generate $meminit cells
case AST_MEMINIT:
{
std::stringstream sstr;
- sstr << (type == AST_MEMWR ? "$memwr$" : "$meminit$") << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
+ sstr << "$meminit$" << str << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
+
+ SigSpec en_sig = children[2]->genRTLIL();
- RTLIL::Cell *cell = current_module->addCell(sstr.str(), type == AST_MEMWR ? ID($memwr) : ID($meminit));
+ RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($meminit_v2));
set_src_attr(cell, this);
int mem_width, mem_size, addr_bits;
id2ast->meminfo(mem_width, mem_size, addr_bits);
- int num_words = 1;
- if (type == AST_MEMINIT) {
- if (children[2]->type != AST_CONSTANT)
- log_file_error(filename, location.first_line, "Memory init with non-constant word count!\n");
- num_words = int(children[2]->asInt(false));
- cell->parameters[ID::WORDS] = RTLIL::Const(num_words);
- }
+ if (children[3]->type != AST_CONSTANT)
+ log_file_error(filename, location.first_line, "Memory init with non-constant word count!\n");
+ int num_words = int(children[3]->asInt(false));
+ cell->parameters[ID::WORDS] = RTLIL::Const(num_words);
SigSpec addr_sig = children[0]->genRTLIL();
cell->setPort(ID::ADDR, addr_sig);
- cell->setPort(ID::DATA, children[1]->genWidthRTLIL(current_module->memories[str]->width * num_words));
+ cell->setPort(ID::DATA, children[1]->genWidthRTLIL(current_module->memories[str]->width * num_words, true));
+ cell->setPort(ID::EN, en_sig);
cell->parameters[ID::MEMID] = RTLIL::Const(str);
cell->parameters[ID::ABITS] = RTLIL::Const(GetSize(addr_sig));
cell->parameters[ID::WIDTH] = RTLIL::Const(current_module->memories[str]->width);
- if (type == AST_MEMWR) {
- cell->setPort(ID::CLK, RTLIL::SigSpec(RTLIL::State::Sx, 1));
- cell->setPort(ID::EN, children[2]->genRTLIL());
- cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(0);
- cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(0);
- }
-
cell->parameters[ID::PRIORITY] = RTLIL::Const(autoidx-1);
}
break;
@@ -1728,7 +1891,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
case AST_ASSIGN:
{
RTLIL::SigSpec left = children[0]->genRTLIL();
- RTLIL::SigSpec right = children[1]->genWidthRTLIL(left.size());
+ RTLIL::SigSpec right = children[1]->genWidthRTLIL(left.size(), true);
if (left.has_const()) {
RTLIL::SigSpec new_left, new_right;
for (int i = 0; i < GetSize(left); i++)
@@ -1768,21 +1931,15 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
continue;
}
if (child->type == AST_PARASET) {
- int extra_const_flags = 0;
IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str;
- if (child->children[0]->type == AST_REALVALUE) {
+ const AstNode *value = child->children[0];
+ if (value->type == AST_REALVALUE)
log_file_warning(filename, location.first_line, "Replacing floating point parameter %s.%s = %f with string.\n",
- log_id(cell), log_id(paraname), child->children[0]->realvalue);
- extra_const_flags = RTLIL::CONST_FLAG_REAL;
- 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_id(cell), log_id(paraname), value->realvalue);
+ else if (value->type != AST_CONSTANT)
log_file_error(filename, location.first_line, "Parameter %s.%s with non-constant value!\n",
log_id(cell), log_id(paraname));
- cell->parameters[paraname] = child->children[0]->asParaConst();
- cell->parameters[paraname].flags |= extra_const_flags;
+ cell->parameters[paraname] = value->asParaConst();
continue;
}
if (child->type == AST_ARGUMENT) {
@@ -1799,7 +1956,12 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (sig.is_wire()) {
// if the resulting SigSpec is a wire, its
// signedness should match that of the AstNode
- log_assert(arg->is_signed == sig.as_wire()->is_signed);
+ if (arg->type == AST_IDENTIFIER && arg->id2ast && arg->id2ast->is_signed && !arg->is_signed)
+ // fully-sliced signed wire will be resolved
+ // once the module becomes available
+ log_assert(attributes.count(ID::reprocess_after));
+ else
+ log_assert(arg->is_signed == sig.as_wire()->is_signed);
} else if (arg->is_signed) {
// non-trivial signed nodes are indirected through
// signed wires to enable sign extension
@@ -1898,6 +2060,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
} break;
+ case AST_BIND: {
+ // Read a bind construct. This should have one or more cells as children.
+ for (RTLIL::Binding *binding : genBindings())
+ current_module->add(binding);
+ break;
+ }
+
case AST_FCALL: {
if (str == "\\$anyconst" || str == "\\$anyseq" || str == "\\$allconst" || str == "\\$allseq")
{
@@ -1943,8 +2112,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
default:
for (auto f : log_files)
current_ast_mod->dumpAst(f, "verilog-ast> ");
- type_name = type2str(type);
- log_file_error(filename, location.first_line, "Don't know how to generate RTLIL code for %s node!\n", type_name.c_str());
+ log_file_error(filename, location.first_line, "Don't know how to generate RTLIL code for %s node!\n", type2str(type).c_str());
}
return RTLIL::SigSpec();
@@ -1953,14 +2121,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// this is a wrapper for AstNode::genRTLIL() when a specific signal width is requested and/or
// signals must be substituted before being used as input values (used by ProcessGenerator)
// note that this is using some global variables to communicate this special settings to AstNode::genRTLIL().
-RTLIL::SigSpec AstNode::genWidthRTLIL(int width, const dict<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr)
+RTLIL::SigSpec AstNode::genWidthRTLIL(int width, bool sgn, const dict<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr)
{
const dict<RTLIL::SigBit, RTLIL::SigBit> *backup_subst_ptr = genRTLIL_subst_ptr;
if (new_subst_ptr)
genRTLIL_subst_ptr = new_subst_ptr;
- bool sign_hint = true;
+ bool sign_hint = sgn;
int width_hint = width;
detectSignWidthWorker(width_hint, sign_hint);
RTLIL::SigSpec sig = genRTLIL(width_hint, sign_hint);
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 5c4dd290f..18b1e1e11 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -192,6 +192,7 @@ void AstNode::annotateTypedEnums(AstNode *template_node)
log_assert(current_scope.count(enum_type) == 1);
AstNode *enum_node = current_scope.at(enum_type);
log_assert(enum_node->type == AST_ENUM);
+ while (enum_node->simplify(true, false, false, 1, -1, false, true)) { }
//get width from 1st enum item:
log_assert(enum_node->children.size() >= 1);
AstNode *enum_item0 = enum_node->children[0];
@@ -330,6 +331,8 @@ static int size_packed_struct(AstNode *snode, int base_offset)
}
}
// range nodes are now redundant
+ for (AstNode *child : node->children)
+ delete child;
node->children.clear();
}
else if (node->children.size() == 1 && node->children[0]->type == AST_MULTIRANGE) {
@@ -344,6 +347,8 @@ static int size_packed_struct(AstNode *snode, int base_offset)
save_struct_array_width(node, width);
width *= array_count;
// range nodes are now redundant
+ for (AstNode *child : node->children)
+ delete child;
node->children.clear();
}
else if (node->range_left < 0) {
@@ -451,7 +456,7 @@ static AstNode *slice_range(AstNode *rnode, AstNode *snode)
}
-static AstNode *make_struct_member_range(AstNode *node, AstNode *member_node)
+AstNode *AST::make_struct_member_range(AstNode *node, AstNode *member_node)
{
// Work out the range in the packed array that corresponds to a struct member
// taking into account any range operations applicable to the current node
@@ -559,6 +564,227 @@ static std::string prefix_id(const std::string &prefix, const std::string &str)
return prefix + str;
}
+// direct access to this global should be limited to the following two functions
+static const RTLIL::Design *simplify_design_context = nullptr;
+
+void AST::set_simplify_design_context(const RTLIL::Design *design)
+{
+ log_assert(!simplify_design_context || !design);
+ simplify_design_context = design;
+}
+
+// lookup the module with the given name in the current design context
+static const RTLIL::Module* lookup_module(const std::string &name)
+{
+ return simplify_design_context->module(name);
+}
+
+const RTLIL::Module* AstNode::lookup_cell_module()
+{
+ log_assert(type == AST_CELL);
+
+ auto reprocess_after = [this] (const std::string &modname) {
+ if (!attributes.count(ID::reprocess_after))
+ attributes[ID::reprocess_after] = AstNode::mkconst_str(modname);
+ };
+
+ const AstNode *celltype = nullptr;
+ for (const AstNode *child : children)
+ if (child->type == AST_CELLTYPE) {
+ celltype = child;
+ break;
+ }
+ log_assert(celltype != nullptr);
+
+ const RTLIL::Module *module = lookup_module(celltype->str);
+ if (!module)
+ module = lookup_module("$abstract" + celltype->str);
+ if (!module) {
+ if (celltype->str.at(0) != '$')
+ reprocess_after(celltype->str);
+ return nullptr;
+ }
+
+ // build a mapping from true param name to param value
+ size_t para_counter = 0;
+ dict<RTLIL::IdString, RTLIL::Const> cell_params_map;
+ for (AstNode *child : children) {
+ if (child->type != AST_PARASET)
+ continue;
+
+ if (child->str.empty() && para_counter >= module->avail_parameters.size())
+ return nullptr; // let hierarchy handle this error
+ IdString paraname = child->str.empty() ? module->avail_parameters[para_counter++] : child->str;
+
+ const AstNode *value = child->children[0];
+ if (value->type != AST_REALVALUE && value->type != AST_CONSTANT)
+ return nullptr; // let genrtlil handle this error
+ cell_params_map[paraname] = value->asParaConst();
+ }
+
+ // put the parameters in order and generate the derived module name
+ std::vector<std::pair<RTLIL::IdString, RTLIL::Const>> named_parameters;
+ for (RTLIL::IdString param : module->avail_parameters) {
+ auto it = cell_params_map.find(param);
+ if (it != cell_params_map.end())
+ named_parameters.emplace_back(it->first, it->second);
+ }
+ std::string modname = celltype->str;
+ if (cell_params_map.size()) // not named_parameters to cover hierarchical defparams
+ modname = derived_module_name(celltype->str, named_parameters);
+
+ // try to find the resolved module
+ module = lookup_module(modname);
+ if (!module) {
+ reprocess_after(modname);
+ return nullptr;
+ }
+ return module;
+}
+
+// returns whether an expression contains an unbased unsized literal; does not
+// check the literal exists in a self-determined context
+static bool contains_unbased_unsized(const AstNode *node)
+{
+ if (node->type == AST_CONSTANT)
+ return node->is_unsized;
+ for (const AstNode *child : node->children)
+ if (contains_unbased_unsized(child))
+ return true;
+ return false;
+}
+
+// adds a wire to the current module with the given name that matches the
+// dimensions of the given wire reference
+void add_wire_for_ref(const RTLIL::Wire *ref, const std::string &str)
+{
+ AstNode *left = AstNode::mkconst_int(ref->width - 1 + ref->start_offset, true);
+ AstNode *right = AstNode::mkconst_int(ref->start_offset, true);
+ if (ref->upto)
+ std::swap(left, right);
+ AstNode *range = new AstNode(AST_RANGE, left, right);
+
+ AstNode *wire = new AstNode(AST_WIRE, range);
+ wire->is_signed = ref->is_signed;
+ wire->is_logic = true;
+ wire->str = str;
+
+ current_ast_mod->children.push_back(wire);
+ current_scope[str] = wire;
+}
+
+enum class IdentUsage {
+ NotReferenced, // target variable is neither read or written in the block
+ Assigned, // target variable is always assigned before use
+ SyncRequired, // target variable may be used before it has been assigned
+};
+
+// determines whether a local variable a block is always assigned before it is
+// used, meaning the nosync attribute can automatically be added to that
+// variable
+static IdentUsage always_asgn_before_use(const AstNode *node, const std::string &target)
+{
+ // This variable has been referenced before it has necessarily been assigned
+ // a value in this procedure.
+ if (node->type == AST_IDENTIFIER && node->str == target)
+ return IdentUsage::SyncRequired;
+
+ // For case statements (which are also used for if/else), we check each
+ // possible branch. If the variable is assigned in all branches, then it is
+ // assigned, and a sync isn't required. If it used before assignment in any
+ // branch, then a sync is required.
+ if (node->type == AST_CASE) {
+ bool all_defined = true;
+ bool any_used = false;
+ bool has_default = false;
+ for (const AstNode *child : node->children) {
+ if (child->type == AST_COND && child->children.at(0)->type == AST_DEFAULT)
+ has_default = true;
+ IdentUsage nested = always_asgn_before_use(child, target);
+ if (nested != IdentUsage::Assigned && child->type == AST_COND)
+ all_defined = false;
+ if (nested == IdentUsage::SyncRequired)
+ any_used = true;
+ }
+ if (any_used)
+ return IdentUsage::SyncRequired;
+ else if (all_defined && has_default)
+ return IdentUsage::Assigned;
+ else
+ return IdentUsage::NotReferenced;
+ }
+
+ // Check if this is an assignment to the target variable. For simplicity, we
+ // don't analyze sub-ranges of the variable.
+ if (node->type == AST_ASSIGN_EQ) {
+ const AstNode *ident = node->children.at(0);
+ if (ident->type == AST_IDENTIFIER && ident->str == target)
+ return IdentUsage::Assigned;
+ }
+
+ for (const AstNode *child : node->children) {
+ IdentUsage nested = always_asgn_before_use(child, target);
+ if (nested != IdentUsage::NotReferenced)
+ return nested;
+ }
+ return IdentUsage::NotReferenced;
+}
+
+static const std::string auto_nosync_prefix = "\\AutoNosync";
+
+// mark a local variable in an always_comb block for automatic nosync
+// consideration
+static void mark_auto_nosync(AstNode *block, const AstNode *wire)
+{
+ log_assert(block->type == AST_BLOCK);
+ log_assert(wire->type == AST_WIRE);
+ block->attributes[auto_nosync_prefix + wire->str] = AstNode::mkconst_int(1,
+ false);
+}
+
+// check a procedural block for auto-nosync markings, remove them, and add
+// nosync to local variables as necessary
+static void check_auto_nosync(AstNode *node)
+{
+ std::vector<RTLIL::IdString> attrs_to_drop;
+ for (const auto& elem : node->attributes) {
+ // skip attributes that don't begin with the prefix
+ if (elem.first.compare(0, auto_nosync_prefix.size(),
+ auto_nosync_prefix.c_str()))
+ continue;
+
+ // delete and remove the attribute once we're done iterating
+ attrs_to_drop.push_back(elem.first);
+
+ // find the wire based on the attribute
+ std::string wire_name = elem.first.substr(auto_nosync_prefix.size());
+ auto it = current_scope.find(wire_name);
+ if (it == current_scope.end())
+ continue;
+
+ // analyze the usage of the local variable in this block
+ IdentUsage ident_usage = always_asgn_before_use(node, wire_name);
+ if (ident_usage != IdentUsage::Assigned)
+ continue;
+
+ // mark the wire with `nosync`
+ AstNode *wire = it->second;
+ log_assert(wire->type == AST_WIRE);
+ wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false);
+ }
+
+ // remove the attributes we've "consumed"
+ for (const RTLIL::IdString &str : attrs_to_drop) {
+ auto it = node->attributes.find(str);
+ delete it->second;
+ node->attributes.erase(it);
+ }
+
+ // check local variables in any nested blocks
+ for (AstNode *child : node->children)
+ check_auto_nosync(child);
+}
+
// convert the AST into a simpler AST that has all parameters substituted by their
// values, unrolled for-loops, expanded generate blocks, etc. when this function
// is done with an AST it can be converted into RTLIL using genRTLIL().
@@ -866,6 +1092,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
}
}
+
+ for (AstNode *child : children)
+ if (child->type == AST_ALWAYS &&
+ child->attributes.count(ID::always_comb))
+ check_auto_nosync(child);
}
// create name resolution entries for all objects with names
@@ -874,7 +1105,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];
// these nodes appear at the top level in a package and can define names
- if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_TYPEDEF) {
+ if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_TYPEDEF || node->type == AST_FUNCTION || node->type == AST_TASK) {
current_scope[node->str] = node;
}
if (node->type == AST_ENUM) {
@@ -915,6 +1146,113 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
}
+ if (type == AST_CELL) {
+ bool lookup_suggested = false;
+
+ for (AstNode *child : children) {
+ // simplify any parameters to constants
+ if (child->type == AST_PARASET)
+ while (child->simplify(true, false, false, 1, -1, false, true)) { }
+
+ // look for patterns which _may_ indicate ambiguity requiring
+ // resolution of the underlying module
+ if (child->type == AST_ARGUMENT) {
+ if (child->children.size() != 1)
+ continue;
+ const AstNode *value = child->children[0];
+ if (value->type == AST_IDENTIFIER) {
+ const AstNode *elem = value->id2ast;
+ if (elem == nullptr) {
+ if (current_scope.count(value->str))
+ elem = current_scope.at(value->str);
+ else
+ continue;
+ }
+ if (elem->type == AST_MEMORY)
+ // need to determine is the is a read or wire
+ lookup_suggested = true;
+ else if (elem->type == AST_WIRE && elem->is_signed && !value->children.empty())
+ // this may be a fully sliced signed wire which needs
+ // to be indirected to produce an unsigned connection
+ lookup_suggested = true;
+ }
+ else if (contains_unbased_unsized(value))
+ // unbased unsized literals extend to width of the context
+ lookup_suggested = true;
+ }
+ }
+
+ const RTLIL::Module *module = nullptr;
+ if (lookup_suggested)
+ module = lookup_cell_module();
+ if (module) {
+ size_t port_counter = 0;
+ for (AstNode *child : children) {
+ if (child->type != AST_ARGUMENT)
+ continue;
+
+ // determine the full name of port this argument is connected to
+ RTLIL::IdString port_name;
+ if (child->str.size())
+ port_name = child->str;
+ else {
+ if (port_counter >= module->ports.size())
+ log_file_error(filename, location.first_line,
+ "Cell instance has more ports than the module!\n");
+ port_name = module->ports[port_counter++];
+ }
+
+ // find the port's wire in the underlying module
+ const RTLIL::Wire *ref = module->wire(port_name);
+ if (ref == nullptr)
+ log_file_error(filename, location.first_line,
+ "Cell instance refers to port %s which does not exist in module %s!.\n",
+ log_id(port_name), log_id(module->name));
+
+ // select the argument, if present
+ log_assert(child->children.size() <= 1);
+ if (child->children.empty())
+ continue;
+ AstNode *arg = child->children[0];
+
+ // plain identifiers never need indirection; this also prevents
+ // adding infinite levels of indirection
+ if (arg->type == AST_IDENTIFIER && arg->children.empty())
+ continue;
+
+ // only add indirection for standard inputs or outputs
+ if (ref->port_input == ref->port_output)
+ continue;
+
+ did_something = true;
+
+ // create the indirection wire
+ std::stringstream sstr;
+ sstr << "$indirect$" << ref->name.c_str() << "$" << filename << ":" << location.first_line << "$" << (autoidx++);
+ std::string tmp_str = sstr.str();
+ add_wire_for_ref(ref, tmp_str);
+
+ AstNode *asgn = new AstNode(AST_ASSIGN);
+ current_ast_mod->children.push_back(asgn);
+
+ AstNode *ident = new AstNode(AST_IDENTIFIER);
+ ident->str = tmp_str;
+ child->children[0] = ident->clone();
+
+ if (ref->port_input && !ref->port_output) {
+ asgn->children.push_back(ident);
+ asgn->children.push_back(arg);
+ } else {
+ log_assert(!ref->port_input && ref->port_output);
+ asgn->children.push_back(arg);
+ asgn->children.push_back(ident);
+ }
+ }
+
+
+ }
+ }
+
int backup_width_hint = width_hint;
bool backup_sign_hint = sign_hint;
@@ -1168,8 +1506,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (const_fold && type == AST_CASE)
{
+ detectSignWidth(width_hint, sign_hint);
while (children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { }
if (children[0]->type == AST_CONSTANT && children[0]->bits_only_01()) {
+ RTLIL::Const case_expr = children[0]->bitsAsConst(width_hint, sign_hint);
std::vector<AstNode*> new_children;
new_children.push_back(children[0]);
for (int i = 1; i < GetSize(children); i++) {
@@ -1182,7 +1522,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
continue;
while (v->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) { }
if (v->type == AST_CONSTANT && v->bits_only_01()) {
- if (v->bits == children[0]->bits) {
+ RTLIL::Const case_item_expr = v->bitsAsConst(width_hint, sign_hint);
+ RTLIL::Const match = const_eq(case_expr, case_item_expr, sign_hint, sign_hint, 1);
+ log_assert(match.bits.size() == 1);
+ if (match.bits.front() == RTLIL::State::S1) {
while (i+1 < GetSize(children))
delete children[++i];
goto keep_const_cond;
@@ -1201,6 +1544,14 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
}
+ dict<std::string, pool<int>> backup_memwr_visible;
+ dict<std::string, pool<int>> final_memwr_visible;
+
+ if (type == AST_CASE && stage == 2) {
+ backup_memwr_visible = current_memwr_visible;
+ final_memwr_visible = current_memwr_visible;
+ }
+
// simplify all children first
// (iterate by index as e.g. auto wires can add new children in the process)
for (size_t i = 0; i < children.size(); i++) {
@@ -1263,11 +1614,25 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
flag_autowire = backup_flag_autowire;
unevaluated_tern_branch = backup_unevaluated_tern_branch;
+ if (stage == 2 && type == AST_CASE) {
+ for (auto &x : current_memwr_visible) {
+ for (int y : x.second)
+ final_memwr_visible[x.first].insert(y);
+ }
+ current_memwr_visible = backup_memwr_visible;
+ }
}
for (auto &attr : attributes) {
while (attr.second->simplify(true, false, false, stage, -1, false, true))
did_something = true;
}
+ if (type == AST_CASE && stage == 2) {
+ current_memwr_visible = final_memwr_visible;
+ }
+ if (type == AST_ALWAYS && stage == 2) {
+ current_memwr_visible.clear();
+ current_memwr_count.clear();
+ }
if (reset_width_after_children) {
width_hint = backup_width_hint;
@@ -1363,6 +1728,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (template_node->type == AST_STRUCT || template_node->type == AST_UNION) {
// replace with wire representing the packed structure
newNode = make_packed_struct(template_node, str);
+ newNode->attributes[ID::wiretype] = mkconst_str(resolved_type_node->str);
// add original input/output attribute to resolved wire
newNode->is_input = this->is_input;
newNode->is_output = this->is_output;
@@ -1411,18 +1777,33 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (is_custom_type) {
log_assert(children.size() == 2);
log_assert(children[1]->type == AST_WIRETYPE);
- if (!current_scope.count(children[1]->str))
- log_file_error(filename, location.first_line, "Unknown identifier `%s' used as type name\n", children[1]->str.c_str());
- AstNode *resolved_type_node = current_scope.at(children[1]->str);
+ auto type_name = children[1]->str;
+ if (!current_scope.count(type_name)) {
+ log_file_error(filename, location.first_line, "Unknown identifier `%s' used as type name\n", type_name.c_str());
+ }
+ AstNode *resolved_type_node = current_scope.at(type_name);
if (resolved_type_node->type != AST_TYPEDEF)
- log_file_error(filename, location.first_line, "`%s' does not name a type\n", children[1]->str.c_str());
+ log_file_error(filename, location.first_line, "`%s' does not name a type\n", type_name.c_str());
log_assert(resolved_type_node->children.size() == 1);
AstNode *template_node = resolved_type_node->children[0];
- delete children[1];
- children.pop_back();
// Ensure typedef itself is fully simplified
- while(template_node->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
+ while (template_node->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
+
+ if (template_node->type == AST_STRUCT || template_node->type == AST_UNION) {
+ // replace with wire representing the packed structure
+ newNode = make_packed_struct(template_node, str);
+ newNode->attributes[ID::wiretype] = mkconst_str(resolved_type_node->str);
+ newNode->type = type;
+ current_scope[str] = this;
+ // copy param value, it needs to be 1st value
+ delete children[1];
+ children.pop_back();
+ newNode->children.insert(newNode->children.begin(), children[0]->clone());
+ goto apply_newNode;
+ }
+ delete children[1];
+ children.pop_back();
if (template_node->type == AST_MEMORY)
log_file_error(filename, location.first_line, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str());
@@ -1643,6 +2024,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
newNode = new AstNode(AST_IDENTIFIER, range);
newNode->str = sname;
newNode->basic_prep = true;
+ if (item_node->is_signed)
+ newNode = new AstNode(AST_TO_SIGNED, newNode);
goto apply_newNode;
}
}
@@ -1652,13 +2035,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (type == AST_IDENTIFIER) {
if (current_scope.count(str) == 0) {
AstNode *current_scope_ast = (current_ast_mod == nullptr) ? current_ast : current_ast_mod;
- const std::string& mod_scope = current_scope_ast->str;
- if (str[0] == '\\' && str.substr(0, mod_scope.size()) == mod_scope) {
- std::string new_str = "\\" + str.substr(mod_scope.size() + 1);
- if (current_scope.count(new_str)) {
- str = new_str;
- }
- }
+ str = try_pop_module_prefix();
for (auto node : current_scope_ast->children) {
//log("looking at mod scope child %s\n", type2str(node->type).c_str());
switch (node->type) {
@@ -1712,7 +2089,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
// split memory access with bit select to individual statements
- if (type == AST_IDENTIFIER && children.size() == 2 && children[0]->type == AST_RANGE && children[1]->type == AST_RANGE && !in_lvalue)
+ if (type == AST_IDENTIFIER && children.size() == 2 && children[0]->type == AST_RANGE && children[1]->type == AST_RANGE && !in_lvalue && stage == 2)
{
if (id2ast == NULL || id2ast->type != AST_MEMORY || children[0]->children.size() != 1)
log_file_error(filename, location.first_line, "Invalid bit-select on memory access!\n");
@@ -1964,6 +2341,16 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
{
expand_genblock(str + ".");
+ // if this is an autonamed block is in an always_comb
+ if (current_always && current_always->attributes.count(ID::always_comb)
+ && str.at(0) == '$')
+ // track local variables in this block so we can consider adding
+ // nosync once the block has been fully elaborated
+ for (AstNode *child : children)
+ if (child->type == AST_WIRE &&
+ !child->attributes.count(ID::nosync))
+ mark_auto_nosync(this, child);
+
std::vector<AstNode*> new_children;
for (size_t i = 0; i < children.size(); i++)
if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) {
@@ -2180,6 +2567,21 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
children.push_back(node);
did_something = true;
}
+ else if (str == "buf" || str == "not")
+ {
+ AstNode *input = children_list.back();
+ if (str == "not")
+ input = new AstNode(AST_BIT_NOT, input);
+
+ newNode = new AstNode(AST_GENBLOCK);
+ for (auto it = children_list.begin(); it != std::prev(children_list.end()); it++) {
+ newNode->children.push_back(new AstNode(AST_ASSIGN, *it, input->clone()));
+ newNode->children.back()->was_checked = true;
+ }
+ delete input;
+
+ did_something = true;
+ }
else
{
AstNodeType op_type = AST_NONE;
@@ -2197,10 +2599,6 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
op_type = AST_BIT_XOR;
if (str == "xnor")
op_type = AST_BIT_XOR, invert_results = true;
- if (str == "buf")
- op_type = AST_POS;
- if (str == "not")
- op_type = AST_POS, invert_results = true;
log_assert(op_type != AST_NONE);
AstNode *node = children_list[1];
@@ -2252,6 +2650,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
+ delete left_at_zero_ast;
+ delete right_at_zero_ast;
}
bool use_case_method = false;
@@ -2554,12 +2954,12 @@ skip_dynamic_range_lvalue_expansion:;
current_scope[wire_addr->str] = wire_addr;
while (wire_addr->simplify(true, false, false, 1, -1, false, false)) { }
- AstNode *assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false));
+ AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_addr, false));
assign_addr->children[0]->str = id_addr;
assign_addr->children[0]->was_checked = true;
defNode->children.push_back(assign_addr);
- assign_addr = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
+ assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->children[0]->clone());
assign_addr->children[0]->str = id_addr;
assign_addr->children[0]->was_checked = true;
newNode->children.push_back(assign_addr);
@@ -2580,7 +2980,7 @@ skip_dynamic_range_lvalue_expansion:;
current_scope[wire_data->str] = wire_data;
while (wire_data->simplify(true, false, false, 1, -1, false, false)) { }
- AstNode *assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false));
+ AstNode *assign_data = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bits_data, false));
assign_data->children[0]->str = id_data;
assign_data->children[0]->was_checked = true;
defNode->children.push_back(assign_data);
@@ -2589,25 +2989,20 @@ skip_dynamic_range_lvalue_expansion:;
node_data->str = id_data;
}
- AstNode *node_en = nullptr;
- if (current_always->type == AST_INITIAL) {
- node_en = AstNode::mkconst_int(1, false);
- } else {
- AstNode *wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
- wire_en->str = id_en;
- wire_en->was_checked = true;
- current_ast_mod->children.push_back(wire_en);
- current_scope[wire_en->str] = wire_en;
- while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
-
- AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width));
- assign_en->children[0]->str = id_en;
- assign_en->children[0]->was_checked = true;
- defNode->children.push_back(assign_en);
+ AstNode *wire_en = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
+ wire_en->str = id_en;
+ wire_en->was_checked = true;
+ current_ast_mod->children.push_back(wire_en);
+ current_scope[wire_en->str] = wire_en;
+ while (wire_en->simplify(true, false, false, 1, -1, false, false)) { }
- node_en = new AstNode(AST_IDENTIFIER);
- node_en->str = id_en;
- }
+ AstNode *assign_en_first = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, mem_width));
+ assign_en_first->children[0]->str = id_en;
+ assign_en_first->children[0]->was_checked = true;
+ defNode->children.push_back(assign_en_first);
+
+ AstNode *node_en = new AstNode(AST_IDENTIFIER);
+ node_en->str = id_en;
if (!defNode->children.empty())
current_top_block->children.insert(current_top_block->children.begin(), defNode);
@@ -2626,18 +3021,16 @@ skip_dynamic_range_lvalue_expansion:;
std::vector<RTLIL::State> padding_x(offset, RTLIL::State::Sx);
- assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
+ assign_data = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER),
new AstNode(AST_CONCAT, mkconst_bits(padding_x, false), children[1]->clone()));
assign_data->children[0]->str = id_data;
assign_data->children[0]->was_checked = true;
- if (current_always->type != AST_INITIAL) {
- for (int i = 0; i < mem_width; i++)
- set_bits_en[i] = offset <= i && i < offset+width ? RTLIL::State::S1 : RTLIL::State::S0;
- assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
- assign_en->children[0]->str = id_en;
- assign_en->children[0]->was_checked = true;
- }
+ for (int i = 0; i < mem_width; i++)
+ set_bits_en[i] = offset <= i && i < offset+width ? RTLIL::State::S1 : RTLIL::State::S0;
+ assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
+ assign_en->children[0]->str = id_en;
+ assign_en->children[0]->was_checked = true;
}
else
{
@@ -2655,19 +3048,17 @@ skip_dynamic_range_lvalue_expansion:;
log_file_error(filename, location.first_line, "Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
- assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
+ assign_data = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER),
new AstNode(AST_SHIFT_LEFT, children[1]->clone(), offset_ast->clone()));
assign_data->children[0]->str = id_data;
assign_data->children[0]->was_checked = true;
- if (current_always->type != AST_INITIAL) {
- for (int i = 0; i < mem_width; i++)
- set_bits_en[i] = i < width ? RTLIL::State::S1 : RTLIL::State::S0;
- assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER),
- new AstNode(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone()));
- assign_en->children[0]->str = id_en;
- assign_en->children[0]->was_checked = true;
- }
+ for (int i = 0; i < mem_width; i++)
+ set_bits_en[i] = i < width ? RTLIL::State::S1 : RTLIL::State::S0;
+ assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER),
+ new AstNode(AST_SHIFT_LEFT, mkconst_bits(set_bits_en, false), offset_ast->clone()));
+ assign_en->children[0]->str = id_en;
+ assign_en->children[0]->was_checked = true;
delete left_at_zero_ast;
delete right_at_zero_ast;
@@ -2677,26 +3068,42 @@ skip_dynamic_range_lvalue_expansion:;
else
{
if (!(children[0]->children.size() == 1 && children[1]->isConst())) {
- assign_data = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), children[1]->clone());
+ assign_data = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[1]->clone());
assign_data->children[0]->str = id_data;
assign_data->children[0]->was_checked = true;
}
- if (current_always->type != AST_INITIAL) {
- assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
- assign_en->children[0]->str = id_en;
- assign_en->children[0]->was_checked = true;
- }
+ assign_en = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), mkconst_bits(set_bits_en, false));
+ assign_en->children[0]->str = id_en;
+ assign_en->children[0]->was_checked = true;
}
if (assign_data)
newNode->children.push_back(assign_data);
if (assign_en)
newNode->children.push_back(assign_en);
- AstNode *wrnode = new AstNode(current_always->type == AST_INITIAL ? AST_MEMINIT : AST_MEMWR, node_addr, node_data, node_en);
+ AstNode *wrnode;
+ if (current_always->type == AST_INITIAL)
+ wrnode = new AstNode(AST_MEMINIT, node_addr, node_data, node_en, mkconst_int(1, false));
+ else
+ wrnode = new AstNode(AST_MEMWR, node_addr, node_data, node_en);
wrnode->str = children[0]->str;
wrnode->id2ast = children[0]->id2ast;
- current_ast_mod->children.push_back(wrnode);
+ wrnode->location = location;
+ if (wrnode->type == AST_MEMWR) {
+ int portid = current_memwr_count[wrnode->str]++;
+ wrnode->children.push_back(mkconst_int(portid, false));
+ std::vector<RTLIL::State> priority_mask;
+ for (int i = 0; i < portid; i++) {
+ bool has_prio = current_memwr_visible[wrnode->str].count(i);
+ priority_mask.push_back(State(has_prio));
+ }
+ wrnode->children.push_back(mkconst_bits(priority_mask, false));
+ current_memwr_visible[wrnode->str].insert(portid);
+ current_always->children.push_back(wrnode);
+ } else {
+ current_ast_mod->children.push_back(wrnode);
+ }
if (newNode->children.empty()) {
delete newNode;
@@ -3469,6 +3876,8 @@ skip_dynamic_range_lvalue_expansion:;
// convert purely constant arguments into localparams
if (child->is_input && child->type == AST_WIRE && arg->type == AST_CONSTANT && node_contains_assignment_to(decl, child)) {
wire->type = AST_LOCALPARAM;
+ if (wire->attributes.count(ID::nosync))
+ delete wire->attributes.at(ID::nosync);
wire->attributes.erase(ID::nosync);
wire->children.insert(wire->children.begin(), arg->clone());
// args without a range implicitly have width 1
@@ -3492,6 +3901,7 @@ skip_dynamic_range_lvalue_expansion:;
}
// updates the sizing
while (wire->simplify(true, false, false, 1, -1, false, false)) { }
+ delete arg;
continue;
}
AstNode *wire_id = new AstNode(AST_IDENTIFIER);
@@ -3773,7 +4183,11 @@ replace_fcall_later:;
case AST_CAST_SIZE:
if (children.at(0)->type == AST_CONSTANT && children.at(1)->type == AST_CONSTANT) {
int width = children[0]->bitsAsConst().as_int();
- RTLIL::Const val = children[1]->bitsAsConst(width);
+ RTLIL::Const val;
+ if (children[1]->is_unsized)
+ val = children[1]->bitsAsUnsizedConst(width);
+ else
+ val = children[1]->bitsAsConst(width);
newNode = mkconst_bits(val.bits, children[1]->is_signed);
}
break;
@@ -3841,8 +4255,12 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
AstNode *meminit = nullptr;
int next_meminit_cursor=0;
vector<State> meminit_bits;
+ vector<State> en_bits;
int meminit_size=0;
+ for (int i = 0; i < mem_width; i++)
+ en_bits.push_back(State::S1);
+
std::ifstream f;
f.open(mem_filename.c_str());
if (f.fail()) {
@@ -3916,12 +4334,13 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
{
if (meminit != nullptr) {
meminit->children[1] = AstNode::mkconst_bits(meminit_bits, false);
- meminit->children[2] = AstNode::mkconst_int(meminit_size, false);
+ meminit->children[3] = AstNode::mkconst_int(meminit_size, false);
}
meminit = new AstNode(AST_MEMINIT);
meminit->children.push_back(AstNode::mkconst_int(cursor, false));
meminit->children.push_back(nullptr);
+ meminit->children.push_back(AstNode::mkconst_bits(en_bits, false));
meminit->children.push_back(nullptr);
meminit->str = memory->str;
meminit->id2ast = memory;
@@ -3956,7 +4375,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
if (meminit != nullptr) {
meminit->children[1] = AstNode::mkconst_bits(meminit_bits, false);
- meminit->children[2] = AstNode::mkconst_int(meminit_size, false);
+ meminit->children[3] = AstNode::mkconst_int(meminit_size, false);
}
return block;
@@ -3967,7 +4386,7 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m
// prefix is carried forward, but resolution of their children is deferred
void AstNode::expand_genblock(const std::string &prefix)
{
- if (type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE) {
+ if (type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE || type == AST_PREFIX) {
log_assert(!str.empty());
// search starting in the innermost scope and then stepping outward
@@ -4053,10 +4472,15 @@ void AstNode::expand_genblock(const std::string &prefix)
for (size_t i = 0; i < children.size(); i++) {
AstNode *child = children[i];
- // AST_PREFIX member names should not be prefixed; a nested AST_PREFIX
- // still needs to recursed-into
- if (type == AST_PREFIX && i == 1 && child->type == AST_IDENTIFIER)
+ // AST_PREFIX member names should not be prefixed; we recurse into them
+ // as normal to ensure indices and ranges are properly resolved, and
+ // then restore the previous string
+ if (type == AST_PREFIX && i == 1) {
+ std::string backup_scope_name = child->str;
+ child->expand_genblock(prefix);
+ child->str = backup_scope_name;
continue;
+ }
// functions/tasks may reference wires, constants, etc. in this scope
if (child->type == AST_FUNCTION || child->type == AST_TASK)
continue;
@@ -4301,10 +4725,12 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
log_assert(children[0]->type == AST_CONSTANT);
log_assert(children[1]->type == AST_CONSTANT);
log_assert(children[2]->type == AST_CONSTANT);
+ log_assert(children[3]->type == AST_CONSTANT);
int cursor = children[0]->asInt(false);
Const data = children[1]->bitsAsConst();
- int length = children[2]->asInt(false);
+ Const en = children[2]->bitsAsConst();
+ int length = children[3]->asInt(false);
if (length != 0)
{
@@ -4315,10 +4741,37 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
int wordsz = GetSize(data) / length;
for (int i = 0; i < length; i++) {
- block->children.push_back(new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER, new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+i, false))), mkconst_bits(data.extract(i*wordsz, wordsz).bits, false)));
- block->children.back()->children[0]->str = str;
- block->children.back()->children[0]->id2ast = id2ast;
- block->children.back()->children[0]->was_checked = true;
+ int pos = 0;
+ while (pos < wordsz) {
+ if (en[pos] != State::S1) {
+ pos++;
+ } else {
+ int epos = pos + 1;
+ while (epos < wordsz && en[epos] == State::S1)
+ epos++;
+ int clen = epos - pos;
+ AstNode *range = new AstNode(AST_RANGE, AstNode::mkconst_int(cursor+i, false));
+ if (pos != 0 || epos != wordsz) {
+ int left;
+ int right;
+ AstNode *mrange = id2ast->children[0];
+ if (mrange->range_left < mrange->range_right) {
+ right = mrange->range_right - pos;
+ left = mrange->range_right - epos + 1;
+ } else {
+ right = mrange->range_right + pos;
+ left = mrange->range_right + epos - 1;
+ }
+ range = new AstNode(AST_MULTIRANGE, range, new AstNode(AST_RANGE, AstNode::mkconst_int(left, true), AstNode::mkconst_int(right, true)));
+ }
+ AstNode *target = new AstNode(AST_IDENTIFIER, range);
+ target->str = str;
+ target->id2ast = id2ast;
+ target->was_checked = true;
+ block->children.push_back(new AstNode(AST_ASSIGN_EQ, target, mkconst_bits(data.extract(i*wordsz + pos, clen).bits, false)));
+ pos = epos;
+ }
+ }
}
}
@@ -4422,11 +4875,48 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
if (children[0]->children[0]->type == AST_CONSTANT)
{
int id = children[0]->children[0]->integer;
- str = stringf("%s[%d]", str.c_str(), id);
+ int left = id2ast->children[1]->children[0]->integer;
+ int right = id2ast->children[1]->children[1]->integer;
+ bool valid_const_access =
+ (left <= id && id <= right) ||
+ (right <= id && id <= left);
+ if (valid_const_access)
+ {
+ str = stringf("%s[%d]", str.c_str(), id);
+ delete_children();
+ range_valid = false;
+ id2ast = NULL;
+ }
+ else
+ {
+ int width;
+ if (bit_part_sel)
+ {
+ bit_part_sel->dumpAst(nullptr, "? ");
+ if (bit_part_sel->children.size() == 1)
+ width = 0;
+ else
+ width = bit_part_sel->children[0]->integer -
+ bit_part_sel->children[1]->integer;
+ delete bit_part_sel;
+ bit_part_sel = nullptr;
+ }
+ else
+ {
+ width = id2ast->children[0]->children[0]->integer -
+ id2ast->children[0]->children[1]->integer;
+ }
+ width = abs(width) + 1;
- delete_children();
- range_valid = false;
- id2ast = NULL;
+ delete_children();
+
+ std::vector<RTLIL::State> x_bits;
+ for (int i = 0; i < width; i++)
+ x_bits.push_back(RTLIL::State::Sx);
+ AstNode *constant = AstNode::mkconst_bits(x_bits, false);
+ constant->cloneInto(this);
+ delete constant;
+ }
}
else
{
@@ -4663,6 +5153,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed)
{
std::map<std::string, AstNode*> backup_scope = current_scope;
std::map<std::string, AstNode::varinfo_t> variables;
+ std::vector<AstNode*> to_delete;
AstNode *block = new AstNode(AST_BLOCK);
AstNode *result = nullptr;
@@ -4720,6 +5211,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed)
current_scope[stmt->str] = stmt;
block->children.erase(block->children.begin());
+ to_delete.push_back(stmt);
continue;
}
@@ -4732,6 +5224,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall, bool must_succeed)
current_scope[stmt->str] = stmt;
block->children.erase(block->children.begin());
+ to_delete.push_back(stmt);
continue;
}
@@ -4927,12 +5420,20 @@ finished:
delete block;
current_scope = backup_scope;
+ for (auto it : to_delete) {
+ delete it;
+ }
+ to_delete.clear();
+
return result;
}
void AstNode::allocateDefaultEnumValues()
{
log_assert(type==AST_ENUM);
+ log_assert(children.size() > 0);
+ if (children.front()->attributes.count(ID::enum_base_type))
+ return; // already elaborated
int last_enum_int = -1;
for (auto node : children) {
log_assert(node->type==AST_ENUM_ITEM);
@@ -5008,4 +5509,21 @@ std::pair<AstNode*, AstNode*> AstNode::get_tern_choice()
return {choice, not_choice};
}
+std::string AstNode::try_pop_module_prefix() const
+{
+ AstNode *current_scope_ast = (current_ast_mod == nullptr) ? current_ast : current_ast_mod;
+ size_t pos = str.find('.', 1);
+ if (str[0] == '\\' && pos != std::string::npos) {
+ std::string new_str = "\\" + str.substr(pos + 1);
+ if (current_scope.count(new_str)) {
+ std::string prefix = str.substr(0, pos);
+ auto it = current_scope_ast->attributes.find(ID::hdlname);
+ if ((it != current_scope_ast->attributes.end() && it->second->str == prefix)
+ || prefix == current_scope_ast->str)
+ return new_str;
+ }
+ }
+ return str;
+}
+
YOSYS_NAMESPACE_END
diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc
index 9ae3fac2c..19844bda6 100644
--- a/frontends/blif/blifparse.cc
+++ b/frontends/blif/blifparse.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -65,17 +65,21 @@ static std::pair<RTLIL::IdString, int> wideports_split(std::string name)
for (int i = 0; i+1 < GetSize(name); i++) {
if (name[i] == '[')
pos = i;
- else if (name[i] < '0' || name[i] > '9')
+ else if (name[i] != '-' && (name[i] < '0' || name[i] > '9'))
+ pos = -1;
+ else if (name[i] == '-' && ((i != pos+1) || name[i+1] == ']'))
+ pos = -1;
+ else if (i == pos+2 && name[i] == '0' && name[i-1] == '-')
pos = -1;
else if (i == pos+1 && name[i] == '0' && name[i+1] != ']')
pos = -1;
}
if (pos >= 0)
- return std::pair<RTLIL::IdString, int>("\\" + name.substr(0, pos), atoi(name.c_str() + pos+1)+1);
+ return std::pair<RTLIL::IdString, int>("\\" + name.substr(0, pos), atoi(name.c_str() + pos+1));
failed:
- return std::pair<RTLIL::IdString, int>("\\" + name, 0);
+ return std::pair<RTLIL::IdString, int>(RTLIL::IdString(), 0);
}
void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool run_clean, bool sop_mode, bool wideports)
@@ -263,8 +267,8 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
if (wideports) {
std::pair<RTLIL::IdString, int> wp = wideports_split(p);
- if (wp.second > 0) {
- wideports_cache[wp.first].first = std::max(wideports_cache[wp.first].first, wp.second);
+ if (!wp.first.empty() && wp.second >= 0) {
+ wideports_cache[wp.first].first = std::max(wideports_cache[wp.first].first, wp.second + 1);
wideports_cache[wp.first].second = !strcmp(cmd, ".inputs");
}
}
@@ -375,6 +379,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
IdString celltype = RTLIL::escape_id(p);
RTLIL::Cell *cell = module->addCell(NEW_ID, celltype);
+ RTLIL::Module *cell_mod = design->module(celltype);
dict<RTLIL::IdString, dict<int, SigBit>> cell_wideports_cache;
@@ -387,10 +392,10 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
if (wideports) {
std::pair<RTLIL::IdString, int> wp = wideports_split(p);
- if (wp.second > 0)
- cell_wideports_cache[wp.first][wp.second-1] = blif_wire(q);
- else
+ if (wp.first.empty())
cell->setPort(RTLIL::escape_id(p), *q ? blif_wire(q) : SigSpec());
+ else
+ cell_wideports_cache[wp.first][wp.second] = blif_wire(q);
} else {
cell->setPort(RTLIL::escape_id(p), *q ? blif_wire(q) : SigSpec());
}
@@ -399,14 +404,26 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool
for (auto &it : cell_wideports_cache)
{
int width = 0;
+ int offset = 0;
+ bool upto = false;
for (auto &b : it.second)
width = std::max(width, b.first + 1);
+ if (cell_mod) {
+ Wire *cell_port = cell_mod->wire(it.first);
+ if (cell_port && (cell_port->port_input || cell_port->port_output)) {
+ offset = cell_port->start_offset;
+ upto = cell_port->upto;
+ width = cell_port->width;
+ }
+ }
+
SigSpec sig;
for (int i = 0; i < width; i++) {
- if (it.second.count(i))
- sig.append(it.second.at(i));
+ int idx = offset + (upto ? width - 1 - i: i);
+ if (it.second.count(idx))
+ sig.append(it.second.at(idx));
else
sig.append(module->addWire(NEW_ID));
}
diff --git a/frontends/blif/blifparse.h b/frontends/blif/blifparse.h
index 2b84cb795..d7a3c96b1 100644
--- a/frontends/blif/blifparse.h
+++ b/frontends/blif/blifparse.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc
index 312f6d3be..50c25abda 100644
--- a/frontends/json/jsonparse.cc
+++ b/frontends/json/jsonparse.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -539,6 +539,56 @@ void json_import(Design *design, string &modname, JsonNode *node)
json_parse_attr_param(cell->parameters, cell_node->data_dict.at("parameters"));
}
}
+
+ if (node->data_dict.count("memories"))
+ {
+ JsonNode *memories_node = node->data_dict.at("memories");
+
+ if (memories_node->type != 'D')
+ log_error("JSON memories node is not a dictionary.\n");
+
+ for (auto &memory_node_it : memories_node->data_dict)
+ {
+ IdString memory_name = RTLIL::escape_id(memory_node_it.first.c_str());
+ JsonNode *memory_node = memory_node_it.second;
+
+ RTLIL::Memory *mem = new RTLIL::Memory;
+ mem->name = memory_name;
+
+ if (memory_node->type != 'D')
+ log_error("JSON memory node '%s' is not a dictionary.\n", log_id(memory_name));
+
+ if (memory_node->data_dict.count("width") == 0)
+ log_error("JSON memory node '%s' has no width attribute.\n", log_id(memory_name));
+ JsonNode *width_node = memory_node->data_dict.at("width");
+ if (width_node->type != 'N')
+ log_error("JSON memory node '%s' has a non-number width.\n", log_id(memory_name));
+ mem->width = width_node->data_number;
+
+ if (memory_node->data_dict.count("size") == 0)
+ log_error("JSON memory node '%s' has no size attribute.\n", log_id(memory_name));
+ JsonNode *size_node = memory_node->data_dict.at("size");
+ if (size_node->type != 'N')
+ log_error("JSON memory node '%s' has a non-number size.\n", log_id(memory_name));
+ mem->size = size_node->data_number;
+
+ mem->start_offset = 0;
+ if (memory_node->data_dict.count("start_offset") != 0) {
+ JsonNode *val = memory_node->data_dict.at("start_offset");
+ if (val->type == 'N')
+ mem->start_offset = val->data_number;
+ }
+
+ if (memory_node->data_dict.count("attributes"))
+ json_parse_attr_param(mem->attributes, memory_node->data_dict.at("attributes"));
+
+ module->memories[mem->name] = mem;
+ }
+ }
+
+ // remove duplicates from connections array
+ pool<RTLIL::SigSig> unique_connections(module->connections_.begin(), module->connections_.end());
+ module->connections_ = std::vector<RTLIL::SigSig>(unique_connections.begin(), unique_connections.end());
}
struct JsonFrontend : public Frontend {
diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc
index f77d7da56..abf8de4d1 100644
--- a/frontends/liberty/liberty.cc
+++ b/frontends/liberty/liberty.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/frontends/rtlil/rtlil_frontend.cc b/frontends/rtlil/rtlil_frontend.cc
index 00c34175e..5f85ca2b8 100644
--- a/frontends/rtlil/rtlil_frontend.cc
+++ b/frontends/rtlil/rtlil_frontend.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/frontends/rtlil/rtlil_frontend.h b/frontends/rtlil/rtlil_frontend.h
index a420778b0..189260605 100644
--- a/frontends/rtlil/rtlil_frontend.h
+++ b/frontends/rtlil/rtlil_frontend.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/frontends/rtlil/rtlil_lexer.l b/frontends/rtlil/rtlil_lexer.l
index beef220f6..e16413216 100644
--- a/frontends/rtlil/rtlil_lexer.l
+++ b/frontends/rtlil/rtlil_lexer.l
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -79,6 +79,7 @@ USING_YOSYS_NAMESPACE
"global" { return TOK_GLOBAL; }
"init" { return TOK_INIT; }
"update" { return TOK_UPDATE; }
+"memwr" { return TOK_MEMWR; }
"process" { return TOK_PROCESS; }
"end" { return TOK_END; }
diff --git a/frontends/rtlil/rtlil_parser.y b/frontends/rtlil/rtlil_parser.y
index 646489196..7d99b2c42 100644
--- a/frontends/rtlil/rtlil_parser.y
+++ b/frontends/rtlil/rtlil_parser.y
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -22,6 +22,8 @@
*
*/
+%require "3.0"
+
%{
#include <list>
#include "frontends/rtlil/rtlil_frontend.h"
@@ -69,7 +71,7 @@ USING_YOSYS_NAMESPACE
%token TOK_AUTOIDX TOK_MODULE TOK_WIRE TOK_WIDTH TOK_INPUT TOK_OUTPUT TOK_INOUT
%token TOK_CELL TOK_CONNECT TOK_SWITCH TOK_CASE TOK_ASSIGN TOK_SYNC
%token TOK_LOW TOK_HIGH TOK_POSEDGE TOK_NEGEDGE TOK_EDGE TOK_ALWAYS TOK_GLOBAL TOK_INIT
-%token TOK_UPDATE TOK_PROCESS TOK_END TOK_INVALID TOK_EOL TOK_OFFSET
+%token TOK_UPDATE TOK_MEMWR TOK_PROCESS TOK_END TOK_INVALID TOK_EOL TOK_OFFSET
%token TOK_PARAMETER TOK_ATTRIBUTE TOK_MEMORY TOK_SIZE TOK_SIGNED TOK_REAL TOK_UPTO
%type <rsigspec> sigspec_list_reversed
@@ -155,6 +157,7 @@ param_defval_stmt:
TOK_PARAMETER TOK_ID constant EOL {
current_module->avail_parameters($2);
current_module->parameter_default_values[$2] = *$3;
+ delete $3;
free($2);
};
@@ -282,10 +285,8 @@ proc_stmt:
TOK_PROCESS TOK_ID EOL {
if (current_module->processes.count($2) != 0)
rtlil_frontend_yyerror(stringf("RTLIL error: redefinition of process %s.", $2).c_str());
- current_process = new RTLIL::Process;
- current_process->name = $2;
+ current_process = current_module->addProcess($2);
current_process->attributes = attrbuf;
- current_module->processes[$2] = current_process;
switch_stack.clear();
switch_stack.push_back(&current_process->root_case.switches);
case_stack.clear();
@@ -389,6 +390,22 @@ update_list:
delete $3;
delete $4;
} |
+ update_list attr_list TOK_MEMWR TOK_ID sigspec sigspec sigspec constant EOL {
+ RTLIL::MemWriteAction act;
+ act.attributes = attrbuf;
+ act.memid = $4;
+ act.address = *$5;
+ act.data = *$6;
+ act.enable = *$7;
+ act.priority_mask = *$8;
+ current_process->syncs.back()->mem_write_actions.push_back(std::move(act));
+ attrbuf.clear();
+ free($4);
+ delete $5;
+ delete $6;
+ delete $7;
+ delete $8;
+ } |
/* empty */;
constant:
diff --git a/frontends/verific/Makefile.inc b/frontends/verific/Makefile.inc
index 972f4f9f1..c82428613 100644
--- a/frontends/verific/Makefile.inc
+++ b/frontends/verific/Makefile.inc
@@ -10,9 +10,11 @@ EXTRA_TARGETS += share/verific
share/verific:
$(P) rm -rf share/verific.new
$(Q) mkdir -p share/verific.new
+ifneq ($(DISABLE_VERIFIC_VHDL),1)
$(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_1987/. share/verific.new/vhdl_vdbs_1987
$(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_1993/. share/verific.new/vhdl_vdbs_1993
$(Q) cp -r $(VERIFIC_DIR)/vhdl_packages/vdbs_2008/. share/verific.new/vhdl_vdbs_2008
+endif
$(Q) chmod -R a+rX share/verific.new
$(Q) mv share/verific.new share/verific
diff --git a/frontends/verific/README b/frontends/verific/README
index c37d76343..952fb1e0c 100644
--- a/frontends/verific/README
+++ b/frontends/verific/README
@@ -1,11 +1,11 @@
This directory contains Verific bindings for Yosys.
-Use Symbiotic EDA Suite if you need Yosys+Verifc.
-https://www.symbioticeda.com/seda-suite
+Use Tabby CAD Suite from YosysHQ if you need Yosys+Verifc.
+https://www.yosyshq.com/
-Contact office@symbioticeda.com for free evaluation
-binaries of Symbiotic EDA Suite.
+Contact YosysHQ at contact@yosyshq.com for free evaluation
+binaries of Tabby CAD Suite.
Verific Features that should be enabled in your Verific library
diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc
index 7aa3ebcbb..17dbed067 100644
--- a/frontends/verific/verific.cc
+++ b/frontends/verific/verific.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -43,22 +43,25 @@ USING_YOSYS_NAMESPACE
#endif
#include "veri_file.h"
-#include "vhdl_file.h"
#include "hier_tree.h"
#include "VeriModule.h"
#include "VeriWrite.h"
-#include "VhdlUnits.h"
#include "VeriLibrary.h"
-#if defined(YOSYSHQ_VERIFIC_INITSTATE) || defined(YOSYSHQ_VERIFIC_TEMPLATES) || defined(YOSYSHQ_VERIFIC_FORMALAPPS)
-#include "VeriExtensions.h"
+#ifdef VERIFIC_VHDL_SUPPORT
+#include "vhdl_file.h"
+#include "VhdlUnits.h"
+#endif
+
+#ifdef YOSYSHQ_VERIFIC_EXTENSIONS
+#include "InitialAssertions.h"
#endif
#ifndef YOSYSHQ_VERIFIC_API_VERSION
# error "Only YosysHQ flavored Verific is supported. Please contact office@yosyshq.com for commercial support for Yosys+Verific."
#endif
-#if YOSYSHQ_VERIFIC_API_VERSION < 20210103
+#if YOSYSHQ_VERIFIC_API_VERSION < 20210801
# error "Please update your version of YosysHQ flavored Verific."
#endif
@@ -175,8 +178,10 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
return;
if (!type_range->IsTypeEnum())
return;
+#ifdef VERIFIC_VHDL_SUPPORT
if (nl->IsFromVhdl() && strcmp(type_range->GetTypeName(), "STD_LOGIC") == 0)
return;
+#endif
auto type_name = type_range->GetTypeName();
if (!type_name)
return;
@@ -193,7 +198,7 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
p = nullptr;
else
for (auto q = p+2; *q != '\0'; q++)
- if (*q != '0' && *q != '1') {
+ if (*q != '0' && *q != '1' && *q != 'x' && *q != 'z') {
p = nullptr;
break;
}
@@ -202,6 +207,7 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
log_error("Expected TypeRange value '%s' to be of form <decimal>'b<binary>.\n", v);
attributes.emplace(stringf("\\enum_value_%s", p+2), RTLIL::escape_id(k));
}
+#ifdef VERIFIC_VHDL_SUPPORT
else if (nl->IsFromVhdl()) {
// Expect "<binary>" or plain <binary>
auto p = v;
@@ -237,6 +243,7 @@ void VerificImporter::import_attributes(dict<RTLIL::IdString, RTLIL::Const> &att
if (p == nullptr)
log_error("Expected TypeRange value '%s' to be of form \"<binary>\" or <binary>.\n", v);
}
+#endif
}
}
}
@@ -371,7 +378,7 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr
return true;
}
- if (inst->Type() == PRIM_TRI) {
+ if ((inst->Type() == PRIM_TRI) || (inst->Type() == PRIM_BUFIF1)) {
module->addMuxGate(inst_name, RTLIL::State::Sz, net_map_at(inst->GetInput()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput()));
return true;
}
@@ -410,6 +417,42 @@ bool VerificImporter::import_netlist_instance_gates(Instance *inst, RTLIL::IdStr
return true;
}
+ if (inst->Type() == PRIM_DLATCHRS)
+ {
+ if (inst->GetSet()->IsGnd() && inst->GetReset()->IsGnd())
+ module->addDlatch(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ else
+ module->addDlatchsr(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetSet()), net_map_at(inst->GetReset()),
+ net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ return true;
+ }
+
+ if (inst->Type() == PRIM_DFF)
+ {
+ VerificClocking clocking(this, inst->GetClock());
+ log_assert(clocking.disable_sig == State::S0);
+ log_assert(clocking.body_net == nullptr);
+
+ if (inst->GetAsyncCond()->IsGnd())
+ clocking.addDff(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ else
+ clocking.addAldff(inst_name, net_map_at(inst->GetAsyncCond()), net_map_at(inst->GetAsyncVal()),
+ net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ return true;
+ }
+
+ if (inst->Type() == PRIM_DLATCH)
+ {
+ if (inst->GetAsyncCond()->IsGnd()) {
+ module->addDlatch(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ } else {
+ RTLIL::SigSpec sig_set = module->And(NEW_ID, net_map_at(inst->GetAsyncCond()), net_map_at(inst->GetAsyncVal()));
+ RTLIL::SigSpec sig_clr = module->And(NEW_ID, net_map_at(inst->GetAsyncCond()), module->Not(NEW_ID, net_map_at(inst->GetAsyncVal())));
+ module->addDlatchsr(inst_name, net_map_at(inst->GetControl()), sig_set, sig_clr, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ }
+ return true;
+ }
+
return false;
}
@@ -471,7 +514,7 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
return true;
}
- if (inst->Type() == PRIM_TRI) {
+ if ((inst->Type() == PRIM_TRI) || (inst->Type() == PRIM_BUFIF1)) {
cell = module->addMux(inst_name, RTLIL::State::Sz, net_map_at(inst->GetInput()), net_map_at(inst->GetControl()), net_map_at(inst->GetOutput()));
import_attributes(cell->attributes, inst);
return true;
@@ -520,6 +563,34 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
return true;
}
+ if (inst->Type() == PRIM_DFF)
+ {
+ VerificClocking clocking(this, inst->GetClock());
+ log_assert(clocking.disable_sig == State::S0);
+ log_assert(clocking.body_net == nullptr);
+
+ if (inst->GetAsyncCond()->IsGnd())
+ cell = clocking.addDff(inst_name, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ else
+ cell = clocking.addAldff(inst_name, net_map_at(inst->GetAsyncCond()), net_map_at(inst->GetAsyncVal()),
+ net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ import_attributes(cell->attributes, inst);
+ return true;
+ }
+
+ if (inst->Type() == PRIM_DLATCH)
+ {
+ if (inst->GetAsyncCond()->IsGnd()) {
+ cell = module->addDlatch(inst_name, net_map_at(inst->GetControl()), net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ } else {
+ RTLIL::SigSpec sig_set = module->And(NEW_ID, net_map_at(inst->GetAsyncCond()), net_map_at(inst->GetAsyncVal()));
+ RTLIL::SigSpec sig_clr = module->And(NEW_ID, net_map_at(inst->GetAsyncCond()), module->Not(NEW_ID, net_map_at(inst->GetAsyncVal())));
+ cell = module->addDlatchsr(inst_name, net_map_at(inst->GetControl()), sig_set, sig_clr, net_map_at(inst->GetInput()), net_map_at(inst->GetOutput()));
+ }
+ import_attributes(cell->attributes, inst);
+ return true;
+ }
+
#define IN operatorInput(inst)
#define IN1 operatorInput1(inst)
#define IN2 operatorInput2(inst)
@@ -727,28 +798,14 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
}
if (inst->Type() == OPER_NTO1MUX) {
- cell = module->addShr(inst_name, IN2, IN1, net_map_at(inst->GetOutput()));
+ cell = module->addBmux(inst_name, IN2, IN1, net_map_at(inst->GetOutput()));
import_attributes(cell->attributes, inst);
return true;
}
if (inst->Type() == OPER_WIDE_NTO1MUX)
{
- SigSpec data = IN2, out = OUT;
-
- int wordsize_bits = ceil_log2(GetSize(out));
- int wordsize = 1 << wordsize_bits;
-
- SigSpec sel = {IN1, SigSpec(State::S0, wordsize_bits)};
-
- SigSpec padded_data;
- for (int i = 0; i < GetSize(data); i += GetSize(out)) {
- SigSpec d = data.extract(i, GetSize(out));
- d.extend_u0(wordsize);
- padded_data.append(d);
- }
-
- cell = module->addShr(inst_name, padded_data, sel, out);
+ cell = module->addBmux(inst_name, IN2, IN1, OUT);
import_attributes(cell->attributes, inst);
return true;
}
@@ -792,6 +849,74 @@ bool VerificImporter::import_netlist_instance_cells(Instance *inst, RTLIL::IdStr
return true;
}
+ if (inst->Type() == OPER_WIDE_DLATCHRS)
+ {
+ RTLIL::SigSpec sig_set = operatorInport(inst, "set");
+ RTLIL::SigSpec sig_reset = operatorInport(inst, "reset");
+
+ if (sig_set.is_fully_const() && !sig_set.as_bool() && sig_reset.is_fully_const() && !sig_reset.as_bool())
+ cell = module->addDlatch(inst_name, net_map_at(inst->GetControl()), IN, OUT);
+ else
+ cell = module->addDlatchsr(inst_name, net_map_at(inst->GetControl()), sig_set, sig_reset, IN, OUT);
+ import_attributes(cell->attributes, inst);
+
+ return true;
+ }
+
+ if (inst->Type() == OPER_WIDE_DFF)
+ {
+ VerificClocking clocking(this, inst->GetClock());
+ log_assert(clocking.disable_sig == State::S0);
+ log_assert(clocking.body_net == nullptr);
+
+ RTLIL::SigSpec sig_d = IN;
+ RTLIL::SigSpec sig_q = OUT;
+ RTLIL::SigSpec sig_adata = IN1;
+ RTLIL::SigSpec sig_acond = IN2;
+
+ if (sig_acond.is_fully_const() && !sig_acond.as_bool()) {
+ cell = clocking.addDff(inst_name, sig_d, sig_q);
+ import_attributes(cell->attributes, inst);
+ } else {
+ int offset = 0, width = 0;
+ for (offset = 0; offset < GetSize(sig_acond); offset += width) {
+ for (width = 1; offset+width < GetSize(sig_acond); width++)
+ if (sig_acond[offset] != sig_acond[offset+width]) break;
+ cell = clocking.addAldff(module->uniquify(inst_name), sig_acond[offset], sig_adata.extract(offset, width),
+ sig_d.extract(offset, width), sig_q.extract(offset, width));
+ import_attributes(cell->attributes, inst);
+ }
+ }
+
+ return true;
+ }
+
+ if (inst->Type() == OPER_WIDE_DLATCH)
+ {
+ RTLIL::SigSpec sig_d = IN;
+ RTLIL::SigSpec sig_q = OUT;
+ RTLIL::SigSpec sig_adata = IN1;
+ RTLIL::SigSpec sig_acond = IN2;
+
+ if (sig_acond.is_fully_const() && !sig_acond.as_bool()) {
+ cell = module->addDlatch(inst_name, net_map_at(inst->GetControl()), sig_d, sig_q);
+ import_attributes(cell->attributes, inst);
+ } else {
+ int offset = 0, width = 0;
+ for (offset = 0; offset < GetSize(sig_acond); offset += width) {
+ for (width = 1; offset+width < GetSize(sig_acond); width++)
+ if (sig_acond[offset] != sig_acond[offset+width]) break;
+ RTLIL::SigSpec sig_set = module->Mux(NEW_ID, RTLIL::SigSpec(0, width), sig_adata.extract(offset, width), sig_acond[offset]);
+ RTLIL::SigSpec sig_clr = module->Mux(NEW_ID, RTLIL::SigSpec(0, width), module->Not(NEW_ID, sig_adata.extract(offset, width)), sig_acond[offset]);
+ cell = module->addDlatchsr(module->uniquify(inst_name), net_map_at(inst->GetControl()), sig_set, sig_clr,
+ sig_d.extract(offset, width), sig_q.extract(offset, width));
+ import_attributes(cell->attributes, inst);
+ }
+ }
+
+ return true;
+ }
+
#undef IN
#undef IN1
#undef IN2
@@ -917,6 +1042,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
} else {
log("Importing module %s.\n", RTLIL::id2cstr(module->name));
}
+ import_attributes(module->attributes, nl, nl);
SetIter si;
MapIter mi, mi2;
@@ -965,18 +1091,28 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
wire->start_offset = min(portbus->LeftIndex(), portbus->RightIndex());
import_attributes(wire->attributes, portbus, nl);
- if (portbus->GetDir() == DIR_INOUT || portbus->GetDir() == DIR_IN)
+ bool portbus_input = portbus->GetDir() == DIR_INOUT || portbus->GetDir() == DIR_IN;
+ if (portbus_input)
wire->port_input = true;
if (portbus->GetDir() == DIR_INOUT || portbus->GetDir() == DIR_OUT)
wire->port_output = true;
for (int i = portbus->LeftIndex();; i += portbus->IsUp() ? +1 : -1) {
if (portbus->ElementAtIndex(i) && portbus->ElementAtIndex(i)->GetNet()) {
+ bool bit_input = portbus_input;
+ if (portbus->GetDir() == DIR_NONE) {
+ Port *p = portbus->ElementAtIndex(i);
+ bit_input = p->GetDir() == DIR_INOUT || p->GetDir() == DIR_IN;
+ if (bit_input)
+ wire->port_input = true;
+ if (p->GetDir() == DIR_INOUT || p->GetDir() == DIR_OUT)
+ wire->port_output = true;
+ }
net = portbus->ElementAtIndex(i)->GetNet();
RTLIL::SigBit bit(wire, i - wire->start_offset);
if (net_map.count(net) == 0)
net_map[net] = bit;
- else if (wire->port_input)
+ else if (bit_input)
module->connect(net_map_at(net), bit);
else
module->connect(bit, net_map_at(net));
@@ -1003,7 +1139,6 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
module->memories[memory->name] = memory;
int number_of_bits = net->Size();
- number_of_bits = 1 << ceil_log2(number_of_bits);
int bits_in_word = number_of_bits;
FOREACH_PORTREF_OF_NET(net, si, pr) {
if (pr->GetInst()->Type() == OPER_READ_PORT) {
@@ -1474,9 +1609,10 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
continue;
}
-#ifdef YOSYSHQ_VERIFIC_INITSTATE
if (inst->Type() == PRIM_YOSYSHQ_INITSTATE)
{
+ if (verific_verbose)
+ log(" adding YosysHQ init state\n");
SigBit initstate = module->Initstate(new_verific_id(inst));
SigBit sig_o = net_map_at(inst->GetOutput());
module->connect(sig_o, initstate);
@@ -1484,7 +1620,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se
if (!mode_keep)
continue;
}
-#endif
+
if (!mode_keep && verific_sva_prims.count(inst->Type())) {
if (verific_verbose)
log(" skipping SVA cell in non k-mode\n");
@@ -1756,30 +1892,62 @@ Cell *VerificClocking::addDff(IdString name, SigSpec sig_d, SigSpec sig_q, Const
{
log_assert(GetSize(sig_d) == GetSize(sig_q));
- if (GetSize(init_value) != 0) {
- log_assert(GetSize(sig_q) == GetSize(init_value));
- if (sig_q.is_wire()) {
- sig_q.as_wire()->attributes[ID::init] = init_value;
+ auto set_init_attribute = [&](SigSpec &s) {
+ if (GetSize(init_value) == 0)
+ return;
+ log_assert(GetSize(s) == GetSize(init_value));
+ if (s.is_wire()) {
+ s.as_wire()->attributes[ID::init] = init_value;
} else {
- Wire *w = module->addWire(NEW_ID, GetSize(sig_q));
+ Wire *w = module->addWire(NEW_ID, GetSize(s));
w->attributes[ID::init] = init_value;
- module->connect(sig_q, w);
- sig_q = w;
+ module->connect(s, w);
+ s = w;
}
- }
+ };
if (enable_sig != State::S1)
sig_d = module->Mux(NEW_ID, sig_q, sig_d, enable_sig);
if (disable_sig != State::S0) {
- log_assert(gclk == false);
log_assert(GetSize(sig_q) == GetSize(init_value));
+
+ if (gclk) {
+ Wire *pre_d = module->addWire(NEW_ID, GetSize(sig_d));
+ Wire *post_q_w = module->addWire(NEW_ID, GetSize(sig_q));
+
+ Const initval(State::Sx, GetSize(sig_q));
+ int offset = 0;
+ for (auto c : sig_q.chunks()) {
+ if (c.wire && c.wire->attributes.count(ID::init)) {
+ Const val = c.wire->attributes.at(ID::init);
+ for (int i = 0; i < GetSize(c); i++)
+ initval[offset+i] = val[c.offset+i];
+ }
+ offset += GetSize(c);
+ }
+
+ if (!initval.is_fully_undef())
+ post_q_w->attributes[ID::init] = initval;
+
+ module->addMux(NEW_ID, sig_d, init_value, disable_sig, pre_d);
+ module->addMux(NEW_ID, post_q_w, init_value, disable_sig, sig_q);
+
+ SigSpec post_q(post_q_w);
+ set_init_attribute(post_q);
+ return module->addFf(name, pre_d, post_q);
+ }
+
+ set_init_attribute(sig_q);
return module->addAdff(name, clock_sig, disable_sig, sig_d, sig_q, init_value, posedge);
}
- if (gclk)
+ if (gclk) {
+ set_init_attribute(sig_q);
return module->addFf(name, sig_d, sig_q);
+ }
+ set_init_attribute(sig_q);
return module->addDff(name, clock_sig, sig_d, sig_q, posedge);
}
@@ -1788,6 +1956,7 @@ Cell *VerificClocking::addAdff(IdString name, RTLIL::SigSpec sig_arst, SigSpec s
log_assert(gclk == false);
log_assert(disable_sig == State::S0);
+ // FIXME: Adffe
if (enable_sig != State::S1)
sig_d = module->Mux(NEW_ID, sig_q, sig_d, enable_sig);
@@ -1799,12 +1968,48 @@ Cell *VerificClocking::addDffsr(IdString name, RTLIL::SigSpec sig_set, RTLIL::Si
log_assert(gclk == false);
log_assert(disable_sig == State::S0);
+ // FIXME: Dffsre
if (enable_sig != State::S1)
sig_d = module->Mux(NEW_ID, sig_q, sig_d, enable_sig);
return module->addDffsr(name, clock_sig, sig_set, sig_clr, sig_d, sig_q, posedge);
}
+Cell *VerificClocking::addAldff(IdString name, RTLIL::SigSpec sig_aload, RTLIL::SigSpec sig_adata, SigSpec sig_d, SigSpec sig_q)
+{
+ log_assert(disable_sig == State::S0);
+
+ // FIXME: Aldffe
+ if (enable_sig != State::S1)
+ sig_d = module->Mux(NEW_ID, sig_q, sig_d, enable_sig);
+
+ if (gclk) {
+ Wire *pre_d = module->addWire(NEW_ID, GetSize(sig_d));
+ Wire *post_q = module->addWire(NEW_ID, GetSize(sig_q));
+
+ Const initval(State::Sx, GetSize(sig_q));
+ int offset = 0;
+ for (auto c : sig_q.chunks()) {
+ if (c.wire && c.wire->attributes.count(ID::init)) {
+ Const val = c.wire->attributes.at(ID::init);
+ for (int i = 0; i < GetSize(c); i++)
+ initval[offset+i] = val[c.offset+i];
+ }
+ offset += GetSize(c);
+ }
+
+ if (!initval.is_fully_undef())
+ post_q->attributes[ID::init] = initval;
+
+ module->addMux(NEW_ID, sig_d, sig_adata, sig_aload, pre_d);
+ module->addMux(NEW_ID, post_q, sig_adata, sig_aload, sig_q);
+
+ return module->addFf(name, pre_d, post_q);
+ }
+
+ return module->addAldff(name, clock_sig, sig_aload, sig_d, sig_q, sig_adata, posedge);
+}
+
// ==================================================================
struct VerificExtNets
@@ -1951,21 +2156,23 @@ void verific_import(Design *design, const std::map<std::string,std::string> &par
std::set<Netlist*> nl_todo, nl_done;
- VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary("work", 1);
VeriLibrary *veri_lib = veri_file::GetLibrary("work", 1);
Array *netlists = NULL;
Array veri_libs, vhdl_libs;
+#ifdef VERIFIC_VHDL_SUPPORT
+ VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary("work", 1);
if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib);
+#endif
if (veri_lib) veri_libs.InsertLast(veri_lib);
Map verific_params(STRING_HASH);
for (const auto &i : parameters)
verific_params.Insert(i.first.c_str(), i.second.c_str());
-#ifdef YOSYSHQ_VERIFIC_INITSTATE
- InitialAssertionRewriter rw;
- rw.RegisterCallBack();
+#ifdef YOSYSHQ_VERIFIC_EXTENSIONS
+ InitialAssertions::Rewrite("work", &verific_params);
#endif
+
if (top.empty()) {
netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs, &verific_params);
}
@@ -1986,12 +2193,13 @@ void verific_import(Design *design, const std::map<std::string,std::string> &par
}
}
+#ifdef VERIFIC_VHDL_SUPPORT
if (vhdl_lib) {
VhdlDesignUnit *vhdl_unit = vhdl_lib->GetPrimUnit(top.c_str());
if (vhdl_unit)
vhdl_units.InsertLast(vhdl_unit);
}
-
+#endif
netlists = hier_tree::Elaborate(&veri_modules, &vhdl_units, &verific_params);
}
@@ -2028,7 +2236,9 @@ void verific_import(Design *design, const std::map<std::string,std::string> &par
}
veri_file::Reset();
+#ifdef VERIFIC_VHDL_SUPPORT
vhdl_file::Reset();
+#endif
Libset::Reset();
verific_incdirs.clear();
verific_libdirs.clear();
@@ -2071,7 +2281,7 @@ struct VerificPass : public Pass {
log("\n");
log("Additional -D<macro>[=<value>] options may be added after the option indicating\n");
log("the language version (and before file names) to set additional verilog defines.\n");
- log("The macros SYNTHESIS and VERIFIC are defined implicitly.\n");
+ log("The macros YOSYS, SYNTHESIS, and VERIFIC are defined implicitly.\n");
log("\n");
log("\n");
log(" verific -formal <verilog-file>..\n");
@@ -2079,11 +2289,41 @@ struct VerificPass : public Pass {
log("Like -sv, but define FORMAL instead of SYNTHESIS.\n");
log("\n");
log("\n");
+#ifdef VERIFIC_VHDL_SUPPORT
log(" verific {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} <vhdl-file>..\n");
log("\n");
log("Load the specified VHDL files into Verific.\n");
log("\n");
log("\n");
+#endif
+ log(" verific {-f|-F} [-vlog95|-vlog2k|-sv2005|-sv2009|-sv2012|-sv|-formal] <command-file>\n");
+ log("\n");
+ log("Load and execute the specified command file.\n");
+ log("Override verilog parsing mode can be set.\n");
+ log("The macros YOSYS, SYNTHESIS/FORMAL, and VERIFIC are defined implicitly.\n");
+ log("\n");
+ log("Command file parser supports following commands:\n");
+ log(" +define - defines macro\n");
+ log(" -u - upper case all identifier (makes Verilog parser case insensitive)\n");
+ log(" -v - register library name (file)\n");
+ log(" -y - register library name (directory)\n");
+ log(" +incdir - specify include dir\n");
+ log(" +libext - specify library extension\n");
+ log(" +liborder - add library in ordered list\n");
+ log(" +librescan - unresolved modules will be always searched starting with the first\n");
+ log(" library specified by -y/-v options.\n");
+ log(" -f/-file - nested -f option\n");
+ log(" -F - nested -F option\n");
+ log("\n");
+ log(" parse mode:\n");
+ log(" -ams\n");
+ log(" +systemverilogext\n");
+ log(" +v2k\n");
+ log(" +verilog1995ext\n");
+ log(" +verilog2001ext\n");
+ log(" -sverilog\n");
+ log("\n");
+ log("\n");
log(" verific [-work <libname>] {-sv|-vhdl|...} <hdl-file>\n");
log("\n");
log("Load the specified Verilog/SystemVerilog/VHDL file into the specified library.\n");
@@ -2255,6 +2495,13 @@ struct VerificPass : public Pass {
log(" WARNING: Templates only available in commercial build.\n");
log("\n");
#endif
+ log("\n");
+ log("\n");
+ log(" verific -cfg [<name> [<value>]]\n");
+ log("\n");
+ log("Get/set Verific runtime flags.\n");
+ log("\n");
+ log("\n");
log("Use YosysHQ Tabby CAD Suite if you need Yosys+Verific.\n");
log("https://www.yosyshq.com/\n");
log("\n");
@@ -2283,24 +2530,31 @@ struct VerificPass : public Pass {
Message::SetConsoleOutput(0);
Message::RegisterCallBackMsg(msg_func);
+ RuntimeFlags::SetVar("db_preserve_user_instances", 1);
RuntimeFlags::SetVar("db_preserve_user_nets", 1);
+ RuntimeFlags::SetVar("db_preserve_x", 1);
+
RuntimeFlags::SetVar("db_allow_external_nets", 1);
RuntimeFlags::SetVar("db_infer_wide_operators", 1);
+ RuntimeFlags::SetVar("db_infer_set_reset_registers", 0);
RuntimeFlags::SetVar("veri_extract_dualport_rams", 0);
RuntimeFlags::SetVar("veri_extract_multiport_rams", 1);
+#ifdef VERIFIC_VHDL_SUPPORT
RuntimeFlags::SetVar("vhdl_extract_dualport_rams", 0);
RuntimeFlags::SetVar("vhdl_extract_multiport_rams", 1);
RuntimeFlags::SetVar("vhdl_support_variable_slice", 1);
RuntimeFlags::SetVar("vhdl_ignore_assertion_statements", 0);
- RuntimeFlags::SetVar("veri_preserve_assignments", 1);
RuntimeFlags::SetVar("vhdl_preserve_assignments", 1);
-
- RuntimeFlags::SetVar("veri_preserve_comments",1);
- //RuntimeFlags::SetVar("vhdl_preserve_comments",1);
+ //RuntimeFlags::SetVar("vhdl_preserve_comments", 1);
+ RuntimeFlags::SetVar("vhdl_preserve_drivers", 1);
+#endif
+ RuntimeFlags::SetVar("veri_preserve_assignments", 1);
+ RuntimeFlags::SetVar("veri_preserve_comments", 1);
+ RuntimeFlags::SetVar("veri_preserve_drivers", 1);
// Workaround for VIPER #13851
RuntimeFlags::SetVar("veri_create_name_for_unnamed_gen_block", 1);
@@ -2311,6 +2565,8 @@ struct VerificPass : public Pass {
// https://github.com/YosysHQ/yosys/issues/1055
RuntimeFlags::SetVar("veri_elaborate_top_level_modules_having_interface_ports", 1) ;
+ RuntimeFlags::SetVar("verific_produce_verbose_syntax_error_message", 1);
+
#ifndef DB_PRESERVE_INITIAL_VALUE
# warning Verific was built without DB_PRESERVE_INITIAL_VALUE.
#endif
@@ -2407,6 +2663,65 @@ struct VerificPass : public Pass {
break;
}
+ if (GetSize(args) > argidx && (args[argidx] == "-f" || args[argidx] == "-F"))
+ {
+ unsigned verilog_mode = veri_file::VERILOG_95; // default recommended by Verific
+ bool is_formal = false;
+ const char* filename = nullptr;
+
+ Verific::veri_file::f_file_flags flags = (args[argidx] == "-f") ? veri_file::F_FILE_NONE : veri_file::F_FILE_CAPITAL;
+
+ for (argidx++; argidx < GetSize(args); argidx++) {
+ if (args[argidx] == "-vlog95") {
+ verilog_mode = veri_file::VERILOG_95;
+ continue;
+ } else if (args[argidx] == "-vlog2k") {
+ verilog_mode = veri_file::VERILOG_2K;
+ continue;
+ } else if (args[argidx] == "-sv2005") {
+ verilog_mode = veri_file::SYSTEM_VERILOG_2005;
+ continue;
+ } else if (args[argidx] == "-sv2009") {
+ verilog_mode = veri_file::SYSTEM_VERILOG_2009;
+ continue;
+ } else if (args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal") {
+ verilog_mode = veri_file::SYSTEM_VERILOG;
+ if (args[argidx] == "-formal") is_formal = true;
+ continue;
+ } else if (args[argidx].compare(0, 1, "-") == 0) {
+ cmd_error(args, argidx, "unknown option");
+ goto check_error;
+ }
+
+ if (!filename) {
+ filename = args[argidx].c_str();
+ continue;
+ } else {
+ log_cmd_error("Only one filename can be specified.\n");
+ }
+ }
+ if (!filename)
+ log_cmd_error("Filname must be specified.\n");
+
+ unsigned analysis_mode = verilog_mode; // keep default as provided by user if not defined in file
+ Array *file_names = veri_file::ProcessFFile(filename, flags, analysis_mode);
+ if (analysis_mode != verilog_mode)
+ log_warning("Provided verilog mode differs from one specified in file.\n");
+
+ veri_file::DefineMacro("YOSYS");
+ veri_file::DefineMacro("VERIFIC");
+ veri_file::DefineMacro(is_formal ? "FORMAL" : "SYNTHESIS");
+
+ if (!veri_file::AnalyzeMultipleFiles(file_names, verilog_mode, work.c_str(), veri_file::MFCU)) {
+ verific_error_msg.clear();
+ log_cmd_error("Reading Verilog/SystemVerilog sources failed.\n");
+ }
+
+ delete file_names;
+ verific_import_pending = true;
+ goto check_error;
+ }
+
if (GetSize(args) > argidx && (args[argidx] == "-vlog95" || args[argidx] == "-vlog2k" || args[argidx] == "-sv2005" ||
args[argidx] == "-sv2009" || args[argidx] == "-sv2012" || args[argidx] == "-sv" || args[argidx] == "-formal"))
{
@@ -2426,6 +2741,7 @@ struct VerificPass : public Pass {
else
log_abort();
+ veri_file::DefineMacro("YOSYS");
veri_file::DefineMacro("VERIFIC");
veri_file::DefineMacro(args[argidx] == "-formal" ? "FORMAL" : "SYNTHESIS");
@@ -2463,6 +2779,7 @@ struct VerificPass : public Pass {
goto check_error;
}
+#ifdef VERIFIC_VHDL_SUPPORT
if (GetSize(args) > argidx && args[argidx] == "-vhdl87") {
vhdl_file::SetDefaultLibraryPath((proc_share_dirname() + "verific/vhdl_vdbs_1987").c_str());
for (argidx++; argidx < GetSize(args); argidx++)
@@ -2498,6 +2815,7 @@ struct VerificPass : public Pass {
verific_import_pending = true;
goto check_error;
}
+#endif
#ifdef YOSYSHQ_VERIFIC_FORMALAPPS
if (argidx < GetSize(args) && args[argidx] == "-app")
@@ -2600,10 +2918,12 @@ struct VerificPass : public Pass {
const char* module = nullptr;
bool mode_vhdl = false;
for (argidx++; argidx < GetSize(args); argidx++) {
+#ifdef VERIFIC_VHDL_SUPPORT
if (args[argidx] == "-vhdl") {
mode_vhdl = true;
continue;
}
+#endif
if (args[argidx] == "-verilog") {
mode_vhdl = false;
continue;
@@ -2630,7 +2950,11 @@ struct VerificPass : public Pass {
log_cmd_error("Filname must be specified.\n");
if (mode_vhdl)
+#ifdef VERIFIC_VHDL_SUPPORT
vhdl_file::PrettyPrint(filename, module, work.c_str());
+#else
+ goto check_error;
+#endif
else
veri_file::PrettyPrint(filename, module, work.c_str());
goto check_error;
@@ -2651,7 +2975,7 @@ struct VerificPass : public Pass {
if (!(argidx+1 < GetSize(args)))
cmd_error(args, argidx+1, "No top module specified.\n");
generator->setLogger([](std::string msg) { log("%s",msg.c_str()); } );
-
+
std::string module = args[++argidx];
VeriLibrary* veri_lib = veri_file::GetLibrary(work.c_str(), 1);
VeriModule *veri_module = veri_lib ? veri_lib->GetModule(module.c_str(), 1) : nullptr;
@@ -2805,19 +3129,20 @@ struct VerificPass : public Pass {
std::set<std::string> top_mod_names;
-#ifdef YOSYSHQ_VERIFIC_INITSTATE
- InitialAssertionRewriter rw;
- rw.RegisterCallBack();
+#ifdef YOSYSHQ_VERIFIC_EXTENSIONS
+ InitialAssertions::Rewrite(work, &parameters);
#endif
if (mode_all)
{
log("Running hier_tree::ElaborateAll().\n");
- VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1);
VeriLibrary *veri_lib = veri_file::GetLibrary(work.c_str(), 1);
Array veri_libs, vhdl_libs;
+#ifdef VERIFIC_VHDL_SUPPORT
+ VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1);
if (vhdl_lib) vhdl_libs.InsertLast(vhdl_lib);
+#endif
if (veri_lib) veri_libs.InsertLast(veri_lib);
Array *netlists = hier_tree::ElaborateAll(&veri_libs, &vhdl_libs, &parameters);
@@ -2834,7 +3159,9 @@ struct VerificPass : public Pass {
cmd_error(args, argidx, "No top module specified.\n");
VeriLibrary* veri_lib = veri_file::GetLibrary(work.c_str(), 1);
+#ifdef VERIFIC_VHDL_SUPPORT
VhdlLibrary *vhdl_lib = vhdl_file::GetLibrary(work.c_str(), 1);
+#endif
Array veri_modules, vhdl_units;
for (; argidx < GetSize(args); argidx++)
@@ -2848,14 +3175,14 @@ struct VerificPass : public Pass {
veri_modules.InsertLast(veri_module);
continue;
}
-
+#ifdef VERIFIC_VHDL_SUPPORT
VhdlDesignUnit *vhdl_unit = vhdl_lib ? vhdl_lib->GetPrimUnit(name) : nullptr;
if (vhdl_unit) {
log("Adding VHDL unit '%s' to elaboration queue.\n", name);
vhdl_units.InsertLast(vhdl_unit);
continue;
}
-
+#endif
log_error("Can't find module/unit '%s'.\n", name);
}
@@ -2915,7 +3242,9 @@ struct VerificPass : public Pass {
}
veri_file::Reset();
+#ifdef VERIFIC_VHDL_SUPPORT
vhdl_file::Reset();
+#endif
Libset::Reset();
verific_incdirs.clear();
verific_libdirs.clear();
@@ -2923,6 +3252,65 @@ struct VerificPass : public Pass {
goto check_error;
}
+ if (argidx < GetSize(args) && args[argidx] == "-cfg")
+ {
+ if (argidx+1 == GetSize(args)) {
+ MapIter mi;
+ const char *k, *s;
+ unsigned long v;
+ pool<std::string> lines;
+ FOREACH_MAP_ITEM(RuntimeFlags::GetVarMap(), mi, &k, &v) {
+ lines.insert(stringf("%s %lu", k, v));
+ }
+ FOREACH_MAP_ITEM(RuntimeFlags::GetStringVarMap(), mi, &k, &s) {
+ if (s == nullptr)
+ lines.insert(stringf("%s NULL", k));
+ else
+ lines.insert(stringf("%s \"%s\"", k, s));
+ }
+ lines.sort();
+ for (auto &line : lines)
+ log("verific -cfg %s\n", line.c_str());
+ goto check_error;
+ }
+
+ if (argidx+2 == GetSize(args)) {
+ const char *k = args[argidx+1].c_str();
+ if (RuntimeFlags::HasUnsignedVar(k)) {
+ log("verific -cfg %s %lu\n", k, RuntimeFlags::GetVar(k));
+ goto check_error;
+ }
+ if (RuntimeFlags::HasStringVar(k)) {
+ const char *s = RuntimeFlags::GetStringVar(k);
+ if (s == nullptr)
+ log("verific -cfg %s NULL\n", k);
+ else
+ log("verific -cfg %s \"%s\"\n", k, s);
+ goto check_error;
+ }
+ log_cmd_error("Can't find Verific Runtime flag '%s'.\n", k);
+ }
+
+ if (argidx+3 == GetSize(args)) {
+ const auto &k = args[argidx+1], &v = args[argidx+2];
+ if (v == "NULL") {
+ RuntimeFlags::SetStringVar(k.c_str(), nullptr);
+ goto check_error;
+ }
+ if (v[0] == '"') {
+ std::string s = v.substr(1, GetSize(v)-2);
+ RuntimeFlags::SetStringVar(k.c_str(), v.c_str());
+ goto check_error;
+ }
+ char *endptr;
+ unsigned long n = strtol(v.c_str(), &endptr, 0);
+ if (*endptr == 0) {
+ RuntimeFlags::SetVar(k.c_str(), n);
+ goto check_error;
+ }
+ }
+ }
+
cmd_error(args, argidx, "Missing or unsupported mode parameter.\n");
check_error:
@@ -2958,11 +3346,19 @@ struct ReadPass : public Pass {
log("the language version (and before file names) to set additional verilog defines.\n");
log("\n");
log("\n");
+#ifdef VERIFIC_VHDL_SUPPORT
log(" read {-vhdl87|-vhdl93|-vhdl2k|-vhdl2008|-vhdl} <vhdl-file>..\n");
log("\n");
log("Load the specified VHDL files. (Requires Verific.)\n");
log("\n");
log("\n");
+#endif
+ log(" read {-f|-F} <command-file>\n");
+ log("\n");
+ log("Load and execute the specified command file. (Requires Verific.)\n");
+ log("Check verific command for more information about supported commands in file.\n");
+ log("\n");
+ log("\n");
log(" read -define <macro>[=<value>]..\n");
log("\n");
log("Set global Verilog/SystemVerilog defines.\n");
@@ -3039,6 +3435,7 @@ struct ReadPass : public Pass {
return;
}
+#ifdef VERIFIC_VHDL_SUPPORT
if (args[1] == "-vhdl87" || args[1] == "-vhdl93" || args[1] == "-vhdl2k" || args[1] == "-vhdl2008" || args[1] == "-vhdl") {
if (use_verific) {
args[0] = "verific";
@@ -3048,6 +3445,16 @@ struct ReadPass : public Pass {
}
return;
}
+#endif
+ if (args[1] == "-f" || args[1] == "-F") {
+ if (use_verific) {
+ args[0] = "verific";
+ Pass::call(design, args);
+ } else {
+ cmd_error(args, 1, "This version of Yosys is built without Verific support.\n");
+ }
+ return;
+ }
if (args[1] == "-define") {
if (use_verific) {
diff --git a/frontends/verific/verific.h b/frontends/verific/verific.h
index f168a2588..9d5beb787 100644
--- a/frontends/verific/verific.h
+++ b/frontends/verific/verific.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -50,6 +50,7 @@ struct VerificClocking {
RTLIL::Cell *addDff(IdString name, SigSpec sig_d, SigSpec sig_q, Const init_value = Const());
RTLIL::Cell *addAdff(IdString name, RTLIL::SigSpec sig_arst, SigSpec sig_d, SigSpec sig_q, Const arst_value);
RTLIL::Cell *addDffsr(IdString name, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, SigSpec sig_d, SigSpec sig_q);
+ RTLIL::Cell *addAldff(IdString name, RTLIL::SigSpec sig_aload, RTLIL::SigSpec sig_adata, SigSpec sig_d, SigSpec sig_q);
bool property_matches_sequence(const VerificClocking &seq) const {
if (clock_net != seq.clock_net)
diff --git a/frontends/verific/verificsva.cc b/frontends/verific/verificsva.cc
index 1f5da1b1d..1bbdcf016 100644
--- a/frontends/verific/verificsva.cc
+++ b/frontends/verific/verificsva.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc
index 230dfadbf..a4dfbc7ec 100644
--- a/frontends/verilog/const2ast.cc
+++ b/frontends/verilog/const2ast.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc
index 84966e501..883531e78 100644
--- a/frontends/verilog/preproc.cc
+++ b/frontends/verilog/preproc.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -36,6 +36,7 @@
#include "verilog_frontend.h"
#include "kernel/log.h"
#include <assert.h>
+#include <stack>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
@@ -141,6 +142,16 @@ static std::string next_token(bool pass_newline = false)
return_char(ch);
}
}
+ else if (ch == '\\')
+ {
+ while ((ch = next_char()) != 0) {
+ if (ch < 33 || ch > 126) {
+ return_char(ch);
+ break;
+ }
+ token += ch;
+ }
+ }
else if (ch == '/')
{
if ((ch = next_char()) != 0) {
@@ -334,6 +345,11 @@ define_map_t::add(const std::string &name, const std::string &txt, const arg_map
defines[name] = std::unique_ptr<define_body_t>(new define_body_t(txt, args));
}
+void define_map_t::add(const std::string &name, const define_body_t &body)
+{
+ defines[name] = std::unique_ptr<define_body_t>(new define_body_t(body));
+}
+
void define_map_t::merge(const define_map_t &map)
{
for (const auto &pr : map.defines) {
@@ -440,7 +456,17 @@ static bool read_argument(std::string &dest)
}
}
-static bool try_expand_macro(define_map_t &defines, std::string &tok)
+using macro_arg_stack_t = std::stack<std::pair<std::string, define_body_t>>;
+
+static void restore_macro_arg(define_map_t &defines, macro_arg_stack_t &macro_arg_stack)
+{
+ log_assert(!macro_arg_stack.empty());
+ auto &overwritten_arg = macro_arg_stack.top();
+ defines.add(overwritten_arg.first, overwritten_arg.second);
+ macro_arg_stack.pop();
+}
+
+static bool try_expand_macro(define_map_t &defines, macro_arg_stack_t &macro_arg_stack, std::string &tok)
{
if (tok == "`\"") {
std::string literal("\"");
@@ -450,7 +476,7 @@ static bool try_expand_macro(define_map_t &defines, std::string &tok)
if (ntok == "`\"") {
insert_input(literal+"\"");
return true;
- } else if (!try_expand_macro(defines, ntok)) {
+ } else if (!try_expand_macro(defines, macro_arg_stack, ntok)) {
literal += ntok;
}
}
@@ -495,6 +521,10 @@ static bool try_expand_macro(define_map_t &defines, std::string &tok)
args.push_back(arg);
}
for (const auto &pr : body->args.get_vals(name, args)) {
+ if (const define_body_t *existing = defines.find(pr.first)) {
+ macro_arg_stack.push({pr.first, *existing});
+ insert_input("`__restore_macro_arg ");
+ }
defines.add(pr.first, pr.second);
}
} else {
@@ -725,9 +755,18 @@ frontend_verilog_preproc(std::istream &f,
defines.merge(pre_defines);
defines.merge(global_defines_cache);
+ macro_arg_stack_t macro_arg_stack;
std::vector<std::string> filename_stack;
+ // We are inside pass_level levels of satisfied ifdefs, and then within
+ // fail_level levels of unsatisfied ifdefs. The unsatisfied ones are
+ // always within satisfied ones — even if some condition within is true,
+ // the parent condition failing renders it moot.
int ifdef_fail_level = 0;
int ifdef_pass_level = 0;
+ // For the outermost unsatisfied ifdef, true iff that ifdef already
+ // had a satisfied branch, and further elsif/else branches should be
+ // considered unsatisfied even if the condition is true.
+ // Meaningless if ifdef_fail_level == 0.
bool ifdef_already_satisfied = false;
output_code.clear();
@@ -745,7 +784,7 @@ frontend_verilog_preproc(std::istream &f,
if (ifdef_fail_level > 0)
ifdef_fail_level--;
else if (ifdef_pass_level > 0)
- ifdef_already_satisfied = --ifdef_pass_level;
+ ifdef_pass_level--;
else
log_error("Found %s outside of macro conditional branch!\n", tok.c_str());
continue;
@@ -755,8 +794,9 @@ frontend_verilog_preproc(std::istream &f,
if (ifdef_fail_level == 0) {
if (ifdef_pass_level == 0)
log_error("Found %s outside of macro conditional branch!\n", tok.c_str());
- log_assert(ifdef_already_satisfied);
+ ifdef_pass_level--;
ifdef_fail_level = 1;
+ ifdef_already_satisfied = true;
} else if (ifdef_fail_level == 1 && !ifdef_already_satisfied) {
ifdef_fail_level = 0;
ifdef_pass_level++;
@@ -771,8 +811,9 @@ frontend_verilog_preproc(std::istream &f,
if (ifdef_fail_level == 0) {
if (ifdef_pass_level == 0)
log_error("Found %s outside of macro conditional branch!\n", tok.c_str());
- log_assert(ifdef_already_satisfied);
+ ifdef_pass_level--;
ifdef_fail_level = 1;
+ ifdef_already_satisfied = true;
} else if (ifdef_fail_level == 1 && !ifdef_already_satisfied && defines.find(name)) {
ifdef_fail_level = 0;
ifdef_pass_level++;
@@ -818,7 +859,7 @@ frontend_verilog_preproc(std::istream &f,
if (tok == "`include") {
skip_spaces();
std::string fn = next_token(true);
- while (try_expand_macro(defines, fn)) {
+ while (try_expand_macro(defines, macro_arg_stack, fn)) {
fn = next_token();
}
while (1) {
@@ -925,12 +966,21 @@ frontend_verilog_preproc(std::istream &f,
continue;
}
- if (try_expand_macro(defines, tok))
+ if (tok == "`__restore_macro_arg") {
+ restore_macro_arg(defines, macro_arg_stack);
+ continue;
+ }
+
+ if (try_expand_macro(defines, macro_arg_stack, tok))
continue;
output_code.push_back(tok);
}
+ if (ifdef_fail_level > 0 || ifdef_pass_level > 0) {
+ log_error("Unterminated preprocessor conditional!\n");
+ }
+
std::string output;
for (auto &str : output_code)
output += str;
diff --git a/frontends/verilog/preproc.h b/frontends/verilog/preproc.h
index 673d633c0..330855a92 100644
--- a/frontends/verilog/preproc.h
+++ b/frontends/verilog/preproc.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -42,6 +42,7 @@ struct define_map_t
// Add a definition, overwriting any existing definition for name.
void add(const std::string &name, const std::string &txt, const arg_map_t *args = nullptr);
+ void add(const std::string &name, const define_body_t &body);
// Merge in another map of definitions (which take precedence
// over anything currently defined).
diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc
index e2aecd99b..9b277c6b9 100644
--- a/frontends/verilog/verilog_frontend.cc
+++ b/frontends/verilog/verilog_frontend.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -61,8 +61,6 @@ static void add_package_types(dict<std::string, AST::AstNode *> &user_types, std
}
}
}
- user_type_stack.clear();
- user_type_stack.push_back(new UserTypeMap());
}
struct VerilogFrontend : public Frontend {
@@ -484,6 +482,19 @@ struct VerilogFrontend : public Frontend {
// make package typedefs available to parser
add_package_types(pkg_user_types, design->verilog_packages);
+ UserTypeMap global_types_map;
+ for (auto def : design->verilog_globals) {
+ if (def->type == AST::AST_TYPEDEF) {
+ global_types_map[def->str] = def;
+ }
+ }
+
+ log_assert(user_type_stack.empty());
+ // use previous global typedefs as bottom level of user type stack
+ user_type_stack.push_back(std::move(global_types_map));
+ // add a new empty type map to allow overriding existing global definitions
+ user_type_stack.push_back(UserTypeMap());
+
frontend_verilog_yyset_lineno(1);
frontend_verilog_yyrestart(NULL);
frontend_verilog_yyparse();
@@ -506,6 +517,10 @@ struct VerilogFrontend : public Frontend {
if (!flag_nopp)
delete lexin;
+ // only the previous and new global type maps remain
+ log_assert(user_type_stack.size() == 2);
+ user_type_stack.clear();
+
delete current_ast;
current_ast = NULL;
diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h
index aa7881038..8454e7999 100644
--- a/frontends/verilog/verilog_frontend.h
+++ b/frontends/verilog/verilog_frontend.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -47,7 +47,7 @@ namespace VERILOG_FRONTEND
// names of locally typedef'ed types in a stack
typedef std::map<std::string, AST::AstNode*> UserTypeMap;
- extern std::vector<UserTypeMap *> user_type_stack;
+ extern std::vector<UserTypeMap> user_type_stack;
// names of package typedef'ed types
extern dict<std::string, AST::AstNode*> pkg_user_types;
diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l
index 66772a097..89c1aa895 100644
--- a/frontends/verilog/verilog_lexer.l
+++ b/frontends/verilog/verilog_lexer.l
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -37,6 +37,8 @@
#ifdef __clang__
// bison generates code using the 'register' storage class specifier
#pragma clang diagnostic ignored "-Wdeprecated-register"
+// flex generates weirdly-indented code
+#pragma clang diagnostic ignored "-Wmisleading-indentation"
#endif
#include "kernel/log.h"
@@ -103,7 +105,7 @@ static bool isUserType(std::string &s)
{
// check current scope then outer scopes for a name
for (auto it = user_type_stack.rbegin(); it != user_type_stack.rend(); ++it) {
- if ((*it)->count(s) > 0) {
+ if (it->count(s) > 0) {
return true;
}
}
@@ -260,6 +262,7 @@ static bool isUserType(std::string &s)
"const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); }
"checker" { if (formal_mode) return TOK_CHECKER; SV_KEYWORD(TOK_CHECKER); }
"endchecker" { if (formal_mode) return TOK_ENDCHECKER; SV_KEYWORD(TOK_ENDCHECKER); }
+"bind" { if (formal_mode) return TOK_BIND; SV_KEYWORD(TOK_BIND); }
"final" { SV_KEYWORD(TOK_FINAL); }
"logic" { SV_KEYWORD(TOK_LOGIC); }
"var" { SV_KEYWORD(TOK_VAR); }
@@ -276,8 +279,11 @@ static bool isUserType(std::string &s)
"output" { return TOK_OUTPUT; }
"inout" { return TOK_INOUT; }
"wire" { return TOK_WIRE; }
+"tri" { return TOK_WIRE; }
"wor" { return TOK_WOR; }
+"trior" { return TOK_WOR; }
"wand" { return TOK_WAND; }
+"triand" { return TOK_WAND; }
"reg" { return TOK_REG; }
"integer" { return TOK_INTEGER; }
"signed" { return TOK_SIGNED; }
@@ -431,8 +437,13 @@ supply1 { return TOK_SUPPLY1; }
"/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {
static bool printed_warning = false;
if (!printed_warning) {
- log_warning("Found one of those horrible `(synopsys|synthesis) translate_off' comments.\n"
- "Yosys does support them but it is recommended to use `ifdef constructs instead!\n");
+ log_warning(
+ "Encountered `translate_off' comment! Such legacy hot "
+ "comments are supported by Yosys, but are not part of "
+ "any formal language specification. Using a portable "
+ "and standards-compliant construct such as `ifdef is "
+ "recommended!\n"
+ );
printed_warning = true;
}
BEGIN(SYNOPSYS_TRANSLATE_OFF);
@@ -447,8 +458,13 @@ supply1 { return TOK_SUPPLY1; }
<SYNOPSYS_FLAGS>full_case {
static bool printed_warning = false;
if (!printed_warning) {
- log_warning("Found one of those horrible `(synopsys|synthesis) full_case' comments.\n"
- "Yosys does support them but it is recommended to use Verilog `full_case' attributes instead!\n");
+ log_warning(
+ "Encountered `full_case' comment! Such legacy hot "
+ "comments are supported by Yosys, but are not part of "
+ "any formal language specification. Using the Verilog "
+ "`full_case' attribute or the SystemVerilog `unique' "
+ "or `unique0' keywords is recommended!\n"
+ );
printed_warning = true;
}
return TOK_SYNOPSYS_FULL_CASE;
@@ -456,8 +472,13 @@ supply1 { return TOK_SUPPLY1; }
<SYNOPSYS_FLAGS>parallel_case {
static bool printed_warning = false;
if (!printed_warning) {
- log_warning("Found one of those horrible `(synopsys|synthesis) parallel_case' comments.\n"
- "Yosys does support them but it is recommended to use Verilog `parallel_case' attributes instead!\n");
+ log_warning(
+ "Encountered `parallel_case' comment! Such legacy hot "
+ "comments are supported by Yosys, but are not part of "
+ "any formal language specification. Using the Verilog "
+ "`parallel_case' attribute or the SystemVerilog "
+ "`unique' or `priority' keywords is recommended!\n"
+ );
printed_warning = true;
}
return TOK_SYNOPSYS_PARALLEL_CASE;
@@ -529,11 +550,18 @@ import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ {
".*" { return TOK_WILDCARD_CONNECT; }
-"|=" { SV_KEYWORD(TOK_OR_ASSIGN); }
-"&=" { SV_KEYWORD(TOK_AND_ASSIGN); }
-"+=" { SV_KEYWORD(TOK_PLUS_ASSIGN); }
+"|=" { SV_KEYWORD(TOK_BIT_OR_ASSIGN); }
+"&=" { SV_KEYWORD(TOK_BIT_AND_ASSIGN); }
+"+=" { SV_KEYWORD(TOK_ADD_ASSIGN); }
"-=" { SV_KEYWORD(TOK_SUB_ASSIGN); }
-"^=" { SV_KEYWORD(TOK_XOR_ASSIGN); }
+"^=" { SV_KEYWORD(TOK_BIT_XOR_ASSIGN); }
+"/=" { SV_KEYWORD(TOK_DIV_ASSIGN); }
+"%=" { SV_KEYWORD(TOK_MOD_ASSIGN); }
+"*=" { SV_KEYWORD(TOK_MUL_ASSIGN); }
+"<<=" { SV_KEYWORD(TOK_SHL_ASSIGN); }
+">>=" { SV_KEYWORD(TOK_SHR_ASSIGN); }
+"<<<=" { SV_KEYWORD(TOK_SSHL_ASSIGN); }
+">>>=" { SV_KEYWORD(TOK_SSHR_ASSIGN); }
[-+]?[=*]> {
if (!specify_mode) REJECT;
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index bcba9b76a..171e098a5 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -33,6 +33,8 @@
*
*/
+%require "3.0"
+
%{
#include <list>
#include <stack>
@@ -54,7 +56,7 @@ namespace VERILOG_FRONTEND {
dict<IdString, AstNode*> *attr_list, default_attr_list;
std::stack<dict<IdString, AstNode*> *> attr_list_stack;
dict<IdString, AstNode*> *albuf;
- std::vector<UserTypeMap*> user_type_stack;
+ std::vector<UserTypeMap> user_type_stack;
dict<std::string, AstNode*> pkg_user_types;
std::vector<AstNode*> ast_stack;
struct AstNode *astbuf1, *astbuf2, *astbuf3;
@@ -127,13 +129,22 @@ struct specify_rise_fall {
specify_triple fall;
};
+static void addWiretypeNode(std::string *name, AstNode *node)
+{
+ log_assert(node);
+ node->is_custom_type = true;
+ node->children.push_back(new AstNode(AST_WIRETYPE));
+ node->children.back()->str = *name;
+ delete name;
+}
+
static void addTypedefNode(std::string *name, AstNode *node)
{
log_assert(node);
auto *tnode = new AstNode(AST_TYPEDEF, node);
tnode->str = *name;
- auto user_types = user_type_stack.back();
- (*user_types)[*name] = tnode;
+ auto &user_types = user_type_stack.back();
+ user_types[*name] = tnode;
if (current_ast_mod && current_ast_mod->type == AST_PACKAGE) {
// typedef inside a package so we need the qualified name
auto qname = current_ast_mod->str + "::" + (*name).substr(1);
@@ -145,8 +156,7 @@ static void addTypedefNode(std::string *name, AstNode *node)
static void enterTypeScope()
{
- auto user_types = new UserTypeMap();
- user_type_stack.push_back(user_types);
+ user_type_stack.push_back(UserTypeMap());
}
static void exitTypeScope()
@@ -157,18 +167,24 @@ static void exitTypeScope()
static bool isInLocalScope(const std::string *name)
{
// tests if a name was declared in the current block scope
- auto user_types = user_type_stack.back();
- return (user_types->count(*name) > 0);
+ auto &user_types = user_type_stack.back();
+ return (user_types.count(*name) > 0);
}
static AstNode *getTypeDefinitionNode(std::string type_name)
{
- // return the definition nodes from the typedef statement
- auto user_types = user_type_stack.back();
- log_assert(user_types->count(type_name) > 0);
- auto typedef_node = (*user_types)[type_name];
- log_assert(typedef_node->type == AST_TYPEDEF);
- return typedef_node->children[0];
+ // check current scope then outer scopes for a name
+ for (auto it = user_type_stack.rbegin(); it != user_type_stack.rend(); ++it) {
+ if (it->count(type_name) > 0) {
+ // return the definition nodes from the typedef statement
+ auto typedef_node = (*it)[type_name];
+ log_assert(typedef_node->type == AST_TYPEDEF);
+ return typedef_node->children[0];
+ }
+ }
+
+ // The lexer recognized the name as a TOK_USER_TYPE, but now we can't find it anymore?
+ log_error("typedef for user type `%s' not found", type_name.c_str());
}
static AstNode *copyTypeDefinition(std::string type_name)
@@ -230,6 +246,75 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
node->children.push_back(rangeNode);
}
+static void checkLabelsMatch(const char *element, const std::string *before, const std::string *after)
+{
+ if (!before && after)
+ frontend_verilog_yyerror("%s missing where end label (%s) was given.",
+ element, after->c_str() + 1);
+ if (before && after && *before != *after)
+ frontend_verilog_yyerror("%s (%s) and end label (%s) don't match.",
+ element, before->c_str() + 1, after->c_str() + 1);
+}
+
+// This transforms a loop like
+// for (genvar i = 0; i < 10; i++) begin : blk
+// to
+// genvar _i;
+// for (_i = 0; _i < 10; _i++) begin : blk
+// localparam i = _i;
+// where `_i` is actually some auto-generated name.
+static void rewriteGenForDeclInit(AstNode *loop)
+{
+ // check if this generate for loop contains an inline declaration
+ log_assert(loop->type == AST_GENFOR);
+ AstNode *decl = loop->children[0];
+ if (decl->type == AST_ASSIGN_EQ)
+ return;
+ log_assert(decl->type == AST_GENVAR);
+ log_assert(loop->children.size() == 5);
+
+ // identify each component of the loop
+ AstNode *init = loop->children[1];
+ AstNode *cond = loop->children[2];
+ AstNode *incr = loop->children[3];
+ AstNode *body = loop->children[4];
+ log_assert(init->type == AST_ASSIGN_EQ);
+ log_assert(incr->type == AST_ASSIGN_EQ);
+ log_assert(body->type == AST_GENBLOCK);
+
+ // create a unique name for the genvar
+ std::string old_str = decl->str;
+ std::string new_str = stringf("$genfordecl$%d$%s", autoidx++, old_str.c_str());
+
+ // rename and move the genvar declaration to the containing description
+ decl->str = new_str;
+ loop->children.erase(loop->children.begin());
+ log_assert(current_ast_mod != nullptr);
+ current_ast_mod->children.push_back(decl);
+
+ // create a new localparam with old name so that the items in the loop
+ // can simply use the old name and shadow it as necessary
+ AstNode *indirect = new AstNode(AST_LOCALPARAM);
+ indirect->str = old_str;
+ AstNode *ident = new AstNode(AST_IDENTIFIER);
+ ident->str = new_str;
+ indirect->children.push_back(ident);
+
+ body->children.insert(body->children.begin(), indirect);
+
+ // only perform the renaming for the initialization, guard, and
+ // incrementation to enable proper shadowing of the synthetic localparam
+ std::function<void(AstNode*)> substitute = [&](AstNode *node) {
+ if (node->type == AST_IDENTIFIER && node->str == old_str)
+ node->str = new_str;
+ for (AstNode *child : node->children)
+ substitute(child);
+ };
+ substitute(init);
+ substitute(cond);
+ substitute(incr);
+}
+
%}
%define api.prefix {frontend_verilog_yy}
@@ -254,6 +339,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
bool boolean;
char ch;
int integer;
+ YOSYS_NAMESPACE_PREFIX AST::AstNodeType ast_node_type;
}
%token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
@@ -266,7 +352,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
%token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
%token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT TOK_VAR TOK_WILDCARD_CONNECT
%token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_WAND TOK_WOR TOK_REG TOK_LOGIC
-%token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_PLUS_ASSIGN TOK_ALWAYS TOK_INITIAL
+%token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL
%token TOK_ALWAYS_FF TOK_ALWAYS_COMB TOK_ALWAYS_LATCH
%token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT
%token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR TOK_AUTOMATIC
@@ -280,18 +366,23 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
%token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY
%token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_UNIQUE0 TOK_PRIORITY
%token TOK_STRUCT TOK_PACKED TOK_UNSIGNED TOK_INT TOK_BYTE TOK_SHORTINT TOK_LONGINT TOK_UNION
-%token TOK_OR_ASSIGN TOK_XOR_ASSIGN TOK_AND_ASSIGN TOK_SUB_ASSIGN
+%token TOK_BIT_OR_ASSIGN TOK_BIT_AND_ASSIGN TOK_BIT_XOR_ASSIGN TOK_ADD_ASSIGN
+%token TOK_SUB_ASSIGN TOK_DIV_ASSIGN TOK_MOD_ASSIGN TOK_MUL_ASSIGN
+%token TOK_SHL_ASSIGN TOK_SHR_ASSIGN TOK_SSHL_ASSIGN TOK_SSHR_ASSIGN
+%token TOK_BIND
%type <ast> range range_or_multirange non_opt_range non_opt_multirange
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list non_io_wire_type io_wire_type
%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id integral_number
%type <string> type_name
-%type <ast> opt_enum_init enum_type struct_type non_wire_data_type func_return_type
+%type <ast> opt_enum_init enum_type struct_type enum_struct_type func_return_type typedef_base_type
%type <boolean> opt_property always_comb_or_latch always_or_always_ff
%type <boolean> opt_signedness_default_signed opt_signedness_default_unsigned
-%type <integer> integer_atom_type
+%type <integer> integer_atom_type integer_vector_type
%type <al> attr case_attr
%type <ast> struct_union
+%type <ast_node_type> asgn_binop
+%type <ast> genvar_identifier
%type <specify_target_ptr> specify_target
%type <specify_triple_ptr> specify_triple specify_opt_triple
@@ -345,6 +436,7 @@ design:
typedef_decl design |
package design |
interface design |
+ bind_directive design |
%empty;
attr:
@@ -448,7 +540,6 @@ module:
port_counter = 0;
mod->str = *$4;
append_attr(mod, $1);
- delete $4;
} module_para_opt module_args_opt ';' module_body TOK_ENDMODULE opt_label {
if (port_stubs.size() != 0)
frontend_verilog_yyerror("Missing details for module port `%s'.",
@@ -456,7 +547,10 @@ module:
SET_AST_NODE_LOC(ast_stack.back(), @2, @$);
ast_stack.pop_back();
log_assert(ast_stack.size() == 1);
+ checkLabelsMatch("Module name", $4, $11);
current_ast_mod = NULL;
+ delete $4;
+ delete $11;
exitTypeScope();
};
@@ -494,18 +588,19 @@ optional_comma:
module_arg_opt_assignment:
'=' expr {
if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) {
- AstNode *wire = new AstNode(AST_IDENTIFIER);
- wire->str = ast_stack.back()->children.back()->str;
if (ast_stack.back()->children.back()->is_input) {
AstNode *n = ast_stack.back()->children.back();
if (n->attributes.count(ID::defaultvalue))
delete n->attributes.at(ID::defaultvalue);
n->attributes[ID::defaultvalue] = $2;
- } else
- if (ast_stack.back()->children.back()->is_reg || ast_stack.back()->children.back()->is_logic)
- ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2))));
- else
- ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2));
+ } else {
+ AstNode *wire = new AstNode(AST_IDENTIFIER);
+ wire->str = ast_stack.back()->children.back()->str;
+ if (ast_stack.back()->children.back()->is_reg || ast_stack.back()->children.back()->is_logic)
+ ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2))));
+ else
+ ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2));
+ }
} else
frontend_verilog_yyerror("SystemVerilog interface in module port list cannot have a default value.");
} |
@@ -573,7 +668,10 @@ package:
append_attr(mod, $1);
} ';' package_body TOK_ENDPACKAGE opt_label {
ast_stack.pop_back();
+ checkLabelsMatch("Package name", $4, $9);
current_ast_mod = NULL;
+ delete $4;
+ delete $9;
exitTypeScope();
};
@@ -581,7 +679,7 @@ package_body:
package_body package_body_stmt | %empty;
package_body_stmt:
- typedef_decl | localparam_decl | param_decl;
+ typedef_decl | localparam_decl | param_decl | task_func_decl;
interface:
TOK_INTERFACE {
@@ -611,7 +709,67 @@ interface_body:
interface_body_stmt:
param_decl | localparam_decl | typedef_decl | defparam_decl | wire_decl | always_stmt | assign_stmt |
- modport_stmt;
+ modport_stmt | bind_directive;
+
+bind_directive:
+ TOK_BIND {
+ AstNode *bnode = new AstNode(AST_BIND);
+ ast_stack.back()->children.push_back(bnode);
+ ast_stack.push_back(bnode);
+ }
+ bind_target {
+ // bind_target should have added at least one child
+ log_assert(ast_stack.back()->children.size() >= 1);
+ }
+ TOK_ID {
+ // The single_cell parser in cell_list_no_array uses astbuf1 as
+ // a sort of template for constructing cells.
+ astbuf1 = new AstNode(AST_CELL);
+ astbuf1->children.push_back(new AstNode(AST_CELLTYPE));
+ astbuf1->children[0]->str = *$5;
+ delete $5;
+ }
+ cell_parameter_list_opt cell_list_no_array ';' {
+ // cell_list should have added at least one more child
+ log_assert(ast_stack.back()->children.size() >= 2);
+ delete astbuf1;
+ ast_stack.pop_back();
+ };
+
+// bind_target matches the target of the bind (everything before
+// bind_instantiation in the IEEE 1800 spec).
+//
+// We can't use the BNF from the spec directly because it's ambiguous:
+// something like "bind foo bar_i (.*)" can either be interpreted with "foo" as
+// a module or interface identifier (matching bind_target_scope in the spec) or
+// by considering foo as a degenerate hierarchical identifier with no '.'
+// characters, followed by no bit select (which matches bind_target_instance in
+// the spec).
+//
+// Instead, we resolve everything as an instance name and then deal with the
+// ambiguity when converting to RTLIL / in the hierarchy pass.
+bind_target:
+ bind_target_instance opt_bind_target_instance_list;
+
+// An optional list of target instances for a bind statement, introduced by a
+// colon.
+opt_bind_target_instance_list:
+ ':' bind_target_instance_list |
+ %empty;
+
+bind_target_instance_list:
+ bind_target_instance |
+ bind_target_instance_list ',' bind_target_instance;
+
+// A single target instance for a bind statement. The top of ast_stack will be
+// the bind node where we should add it.
+bind_target_instance:
+ hierarchical_id {
+ auto *node = new AstNode(AST_IDENTIFIER);
+ node->str = *$1;
+ delete $1;
+ ast_stack.back()->children.push_back(node);
+ };
mintypmax_expr:
expr { delete $1; } |
@@ -676,21 +834,10 @@ opt_wire_type_token:
wire_type_token | %empty;
wire_type_token:
- hierarchical_type_id {
- astbuf3->is_custom_type = true;
- astbuf3->children.push_back(new AstNode(AST_WIRETYPE));
- astbuf3->children.back()->str = *$1;
- } |
- TOK_WOR {
- astbuf3->is_wor = true;
- } |
- TOK_WAND {
- astbuf3->is_wand = true;
- } |
- // wires
- TOK_WIRE {
+ // nets
+ net_type {
} |
- TOK_WIRE logic_type {
+ net_type logic_type {
} |
// regs
TOK_REG {
@@ -717,6 +864,15 @@ wire_type_token:
astbuf3->range_right = 0;
};
+net_type:
+ TOK_WOR {
+ astbuf3->is_wor = true;
+ } |
+ TOK_WAND {
+ astbuf3->is_wand = true;
+ } |
+ TOK_WIRE;
+
logic_type:
TOK_LOGIC {
} |
@@ -724,6 +880,9 @@ logic_type:
astbuf3->range_left = $1 - 1;
astbuf3->range_right = 0;
astbuf3->is_signed = true;
+ } |
+ hierarchical_type_id {
+ addWiretypeNode($1, astbuf3);
};
integer_atom_type:
@@ -733,6 +892,10 @@ integer_atom_type:
TOK_LONGINT { $$ = 64; } |
TOK_BYTE { $$ = 8; } ;
+integer_vector_type:
+ TOK_LOGIC { $$ = TOK_LOGIC; } |
+ TOK_REG { $$ = TOK_REG; } ;
+
non_opt_range:
'[' expr ':' expr ']' {
$$ = new AstNode(AST_RANGE);
@@ -787,7 +950,7 @@ module_body:
module_body_stmt:
task_func_decl | specify_block | param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt |
- enum_decl | struct_decl |
+ enum_decl | struct_decl | bind_directive |
always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block;
checker_decl:
@@ -861,6 +1024,7 @@ task_func_decl:
outreg->children.push_back($4);
outreg->is_signed = $4->is_signed;
$4->is_signed = false;
+ outreg->is_custom_type = $4->type == AST_WIRETYPE;
}
current_function_or_task->children.push_back(outreg);
current_function_or_task_port_id = 1;
@@ -871,6 +1035,11 @@ task_func_decl:
};
func_return_type:
+ hierarchical_type_id {
+ $$ = new AstNode(AST_WIRETYPE);
+ $$->str = *$1;
+ delete $1;
+ } |
opt_type_vec opt_signedness_default_unsigned {
$$ = makeRange(0, 0, $2);
} |
@@ -1141,6 +1310,8 @@ specify_item:
cell->children.back()->str = "\\DST";
delete $1;
+ delete limit;
+ delete limit2;
};
specify_opt_triple:
@@ -1438,6 +1609,7 @@ param_type:
astbuf1->is_custom_type = true;
astbuf1->children.push_back(new AstNode(AST_WIRETYPE));
astbuf1->children.back()->str = *$1;
+ delete $1;
};
param_decl:
@@ -1462,7 +1634,26 @@ param_decl_list:
single_param_decl | param_decl_list ',' single_param_decl;
single_param_decl:
- TOK_ID '=' expr {
+ single_param_decl_ident '=' expr {
+ AstNode *decl = ast_stack.back()->children.back();
+ log_assert(decl->type == AST_PARAMETER || decl->type == AST_LOCALPARAM);
+ delete decl->children[0];
+ decl->children[0] = $3;
+ } |
+ single_param_decl_ident {
+ AstNode *decl = ast_stack.back()->children.back();
+ if (decl->type != AST_PARAMETER) {
+ log_assert(decl->type == AST_LOCALPARAM);
+ frontend_verilog_yyerror("localparam initialization is missing!");
+ }
+ if (!sv_mode)
+ frontend_verilog_yyerror("Parameter defaults can only be omitted in SystemVerilog mode!");
+ delete decl->children[0];
+ decl->children.erase(decl->children.begin());
+ };
+
+single_param_decl_ident:
+ TOK_ID {
AstNode *node;
if (astbuf1 == nullptr) {
if (!sv_mode)
@@ -1473,10 +1664,9 @@ single_param_decl:
node = astbuf1->clone();
}
node->str = *$1;
- delete node->children[0];
- node->children[0] = $3;
ast_stack.back()->children.push_back(node);
delete $1;
+ SET_AST_NODE_LOC(node, @1, @1);
};
defparam_decl:
@@ -1509,17 +1699,18 @@ enum_type: TOK_ENUM {
// create the template for the names
astbuf1 = new AstNode(AST_ENUM_ITEM);
astbuf1->children.push_back(AstNode::mkconst_int(0, true));
- } enum_base_type '{' enum_name_list '}' { // create template for the enum vars
- auto tnode = astbuf1->clone();
- delete astbuf1;
- astbuf1 = tnode;
- tnode->type = AST_WIRE;
- tnode->attributes[ID::enum_type] = AstNode::mkconst_str(astbuf2->str);
- // drop constant but keep any range
- delete tnode->children[0];
- tnode->children.erase(tnode->children.begin());
- $$ = astbuf1; }
- ;
+ } enum_base_type '{' enum_name_list optional_comma '}' {
+ // create template for the enum vars
+ auto tnode = astbuf1->clone();
+ delete astbuf1;
+ astbuf1 = tnode;
+ tnode->type = AST_WIRE;
+ tnode->attributes[ID::enum_type] = AstNode::mkconst_str(astbuf2->str);
+ // drop constant but keep any range
+ delete tnode->children[0];
+ tnode->children.erase(tnode->children.begin());
+ $$ = astbuf1;
+ };
enum_base_type: type_atom type_signing
| type_vec type_signing range { if ($3) astbuf1->children.push_back($3); }
@@ -1658,10 +1849,12 @@ member_type_token:
delete astbuf1;
astbuf1 = template_node;
}
- | struct_union {
+ | {
+ delete astbuf1;
+ } struct_union {
// stash state on ast_stack
ast_stack.push_back(astbuf2);
- astbuf2 = $1;
+ astbuf2 = $2;
} struct_body {
astbuf1 = astbuf2;
// recover state
@@ -1867,7 +2060,7 @@ type_name: TOK_ID // first time seen
;
typedef_decl:
- TOK_TYPEDEF non_io_wire_type range type_name range_or_multirange ';' {
+ TOK_TYPEDEF typedef_base_type range type_name range_or_multirange ';' {
astbuf1 = $2;
astbuf2 = checkRange(astbuf1, $3);
if (astbuf2)
@@ -1880,10 +2073,33 @@ typedef_decl:
rewriteAsMemoryNode(astbuf1, $5);
}
addTypedefNode($4, astbuf1); }
- | TOK_TYPEDEF non_wire_data_type type_name ';' { addTypedefNode($3, $2); }
+ | TOK_TYPEDEF enum_struct_type type_name ';' { addTypedefNode($3, $2); }
;
-non_wire_data_type:
+typedef_base_type:
+ hierarchical_type_id {
+ $$ = new AstNode(AST_WIRE);
+ $$->is_logic = true;
+ addWiretypeNode($1, $$);
+ } |
+ integer_vector_type opt_signedness_default_unsigned {
+ $$ = new AstNode(AST_WIRE);
+ if ($1 == TOK_REG) {
+ $$->is_reg = true;
+ } else {
+ $$->is_logic = true;
+ }
+ $$->is_signed = $2;
+ } |
+ integer_atom_type opt_signedness_default_signed {
+ $$ = new AstNode(AST_WIRE);
+ $$->is_logic = true;
+ $$->is_signed = $2;
+ $$->range_left = $1 - 1;
+ $$->range_right = 0;
+ };
+
+enum_struct_type:
enum_type
| struct_type
;
@@ -1920,6 +2136,9 @@ cell_list:
cell_list ',' single_cell;
single_cell:
+ single_cell_no_array | single_cell_arraylist;
+
+single_cell_no_array:
TOK_ID {
astbuf2 = astbuf1->clone();
if (astbuf2->type != AST_PRIMITIVE)
@@ -1928,7 +2147,9 @@ single_cell:
ast_stack.back()->children.push_back(astbuf2);
} '(' cell_port_list ')' {
SET_AST_NODE_LOC(astbuf2, @1, @$);
- } |
+ }
+
+single_cell_arraylist:
TOK_ID non_opt_range {
astbuf2 = astbuf1->clone();
if (astbuf2->type != AST_PRIMITIVE)
@@ -1939,6 +2160,10 @@ single_cell:
SET_AST_NODE_LOC(astbuf2, @1, @$);
};
+cell_list_no_array:
+ single_cell_no_array |
+ cell_list_no_array ',' single_cell_no_array;
+
prim_list:
single_prim |
prim_list ',' single_prim;
@@ -2046,6 +2271,7 @@ cell_port:
if (!sv_mode)
frontend_verilog_yyerror("Wildcard port connections are only supported in SystemVerilog mode.");
astbuf2->attributes[ID::wildcard_port_conns] = AstNode::mkconst_int(1, false);
+ free_attr($1);
};
always_comb_or_latch:
@@ -2417,45 +2643,81 @@ simple_behavioral_stmt:
SET_AST_NODE_LOC(node, @2, @5);
append_attr(node, $1);
} |
- attr lvalue TOK_XOR_ASSIGN delay expr {
- AstNode *xor_node = new AstNode(AST_BIT_XOR, $2->clone(), $5);
- AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, xor_node);
- SET_AST_NODE_LOC(xor_node, @2, @5);
- SET_AST_NODE_LOC(node, @2, @5);
- ast_stack.back()->children.push_back(node);
- append_attr(node, $1);
- } |
- attr lvalue TOK_OR_ASSIGN delay expr {
- AstNode *or_node = new AstNode(AST_BIT_OR, $2->clone(), $5);
- SET_AST_NODE_LOC(or_node, @2, @5);
- AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, or_node);
+ attr lvalue asgn_binop delay expr {
+ AstNode *expr_node = $5;
+ if ($3 == AST_SHIFT_LEFT || $3 == AST_SHIFT_RIGHT ||
+ $3 == AST_SHIFT_SLEFT || $3 == AST_SHIFT_SRIGHT) {
+ expr_node = new AstNode(AST_TO_UNSIGNED, expr_node);
+ SET_AST_NODE_LOC(expr_node, @5, @5);
+ }
+ AstNode *op_node = new AstNode($3, $2->clone(), expr_node);
+ AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, op_node);
+ SET_AST_NODE_LOC(op_node, @2, @5);
SET_AST_NODE_LOC(node, @2, @5);
ast_stack.back()->children.push_back(node);
append_attr(node, $1);
- } |
- attr lvalue TOK_PLUS_ASSIGN delay expr {
- AstNode *add_node = new AstNode(AST_ADD, $2->clone(), $5);
- AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, add_node);
- SET_AST_NODE_LOC(node, @2, @5);
- SET_AST_NODE_LOC(add_node, @2, @5);
+ };
+
+asgn_binop:
+ TOK_BIT_OR_ASSIGN { $$ = AST_BIT_OR; } |
+ TOK_BIT_AND_ASSIGN { $$ = AST_BIT_AND; } |
+ TOK_BIT_XOR_ASSIGN { $$ = AST_BIT_XOR; } |
+ TOK_ADD_ASSIGN { $$ = AST_ADD; } |
+ TOK_SUB_ASSIGN { $$ = AST_SUB; } |
+ TOK_DIV_ASSIGN { $$ = AST_DIV; } |
+ TOK_MOD_ASSIGN { $$ = AST_MOD; } |
+ TOK_MUL_ASSIGN { $$ = AST_MUL; } |
+ TOK_SHL_ASSIGN { $$ = AST_SHIFT_LEFT; } |
+ TOK_SHR_ASSIGN { $$ = AST_SHIFT_RIGHT; } |
+ TOK_SSHL_ASSIGN { $$ = AST_SHIFT_SLEFT; } |
+ TOK_SSHR_ASSIGN { $$ = AST_SHIFT_SRIGHT; } ;
+
+for_initialization:
+ TOK_ID '=' expr {
+ AstNode *ident = new AstNode(AST_IDENTIFIER);
+ ident->str = *$1;
+ AstNode *node = new AstNode(AST_ASSIGN_EQ, ident, $3);
ast_stack.back()->children.push_back(node);
- append_attr(node, $1);
+ SET_AST_NODE_LOC(node, @1, @3);
+ delete $1;
} |
- attr lvalue TOK_SUB_ASSIGN delay expr {
- AstNode *sub_node = new AstNode(AST_SUB, $2->clone(), $5);
- AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, sub_node);
- SET_AST_NODE_LOC(node, @2, @5);
- SET_AST_NODE_LOC(sub_node, @2, @5);
- ast_stack.back()->children.push_back(node);
- append_attr(node, $1);
+ non_io_wire_type range TOK_ID {
+ frontend_verilog_yyerror("For loop variable declaration is missing initialization!");
} |
- attr lvalue TOK_AND_ASSIGN delay expr {
- AstNode *and_node = new AstNode(AST_BIT_AND, $2->clone(), $5);
- AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, and_node);
- SET_AST_NODE_LOC(node, @2, @5);
- SET_AST_NODE_LOC(and_node, @2, @5);
- ast_stack.back()->children.push_back(node);
- append_attr(node, $1);
+ non_io_wire_type range TOK_ID '=' expr {
+ if (!sv_mode)
+ frontend_verilog_yyerror("For loop inline variable declaration is only supported in SystemVerilog mode!");
+
+ // loop variable declaration
+ AstNode *wire = $1;
+ AstNode *range = checkRange(wire, $2);
+ if (range != nullptr)
+ wire->children.push_back(range);
+ SET_AST_NODE_LOC(wire, @1, @3);
+ SET_AST_NODE_LOC(range, @2, @2);
+
+ AstNode *ident = new AstNode(AST_IDENTIFIER);
+ ident->str = *$3;
+ wire->str = *$3;
+ delete $3;
+
+ AstNode *loop = ast_stack.back();
+ AstNode *parent = ast_stack.at(ast_stack.size() - 2);
+ log_assert(parent->children.back() == loop);
+
+ // loop variable initialization
+ AstNode *asgn = new AstNode(AST_ASSIGN_EQ, ident, $5);
+ loop->children.push_back(asgn);
+ SET_AST_NODE_LOC(asgn, @3, @5);
+ SET_AST_NODE_LOC(ident, @3, @3);
+
+ // inject a wrapping block to declare the loop variable and
+ // contain the current loop
+ AstNode *wrapper = new AstNode(AST_BLOCK);
+ wrapper->str = "$fordecl_block$" + std::to_string(autoidx++);
+ wrapper->children.push_back(wire);
+ wrapper->children.push_back(loop);
+ parent->children.back() = wrapper; // replaces `loop`
};
// this production creates the obligatory if-else shift/reduce conflict
@@ -2497,8 +2759,7 @@ behavioral_stmt:
node->str = *$4;
} behavioral_stmt_list TOK_END opt_label {
exitTypeScope();
- if ($4 != NULL && $8 != NULL && *$4 != *$8)
- frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $4->c_str()+1, $8->c_str()+1);
+ checkLabelsMatch("Begin label", $4, $8);
AstNode *node = ast_stack.back();
// In SystemVerilog, unnamed blocks with block item declarations
// create an implicit hierarchy scope
@@ -2519,7 +2780,7 @@ behavioral_stmt:
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
append_attr(node, $1);
- } simple_behavioral_stmt ';' expr {
+ } for_initialization ';' expr {
ast_stack.back()->children.push_back($7);
} ';' simple_behavioral_stmt ')' {
AstNode *block = new AstNode(AST_BLOCK);
@@ -2718,6 +2979,7 @@ rvalue:
hierarchical_id '[' expr ']' '.' rvalue {
$$ = new AstNode(AST_PREFIX, $3, $6);
$$->str = *$1;
+ SET_AST_NODE_LOC($$, @1, @6);
delete $1;
} |
hierarchical_id range {
@@ -2783,16 +3045,50 @@ gen_stmt_or_module_body_stmt:
free_attr($1);
};
+genvar_identifier:
+ TOK_ID {
+ $$ = new AstNode(AST_IDENTIFIER);
+ $$->str = *$1;
+ delete $1;
+ };
+
+genvar_initialization:
+ TOK_GENVAR genvar_identifier {
+ frontend_verilog_yyerror("Generate for loop variable declaration is missing initialization!");
+ } |
+ TOK_GENVAR genvar_identifier '=' expr {
+ if (!sv_mode)
+ frontend_verilog_yyerror("Generate for loop inline variable declaration is only supported in SystemVerilog mode!");
+ AstNode *node = new AstNode(AST_GENVAR);
+ node->is_reg = true;
+ node->is_signed = true;
+ node->range_left = 31;
+ node->range_right = 0;
+ node->str = $2->str;
+ node->children.push_back(checkRange(node, nullptr));
+ ast_stack.back()->children.push_back(node);
+ SET_AST_NODE_LOC(node, @1, @4);
+ node = new AstNode(AST_ASSIGN_EQ, $2, $4);
+ ast_stack.back()->children.push_back(node);
+ SET_AST_NODE_LOC(node, @1, @4);
+ } |
+ genvar_identifier '=' expr {
+ AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $3);
+ ast_stack.back()->children.push_back(node);
+ SET_AST_NODE_LOC(node, @1, @3);
+ };
+
// this production creates the obligatory if-else shift/reduce conflict
gen_stmt:
TOK_FOR '(' {
AstNode *node = new AstNode(AST_GENFOR);
ast_stack.back()->children.push_back(node);
ast_stack.push_back(node);
- } simple_behavioral_stmt ';' expr {
+ } genvar_initialization ';' expr {
ast_stack.back()->children.push_back($6);
} ';' simple_behavioral_stmt ')' gen_stmt_block {
SET_AST_NODE_LOC(ast_stack.back(), @1, @11);
+ rewriteGenForDeclInit(ast_stack.back());
ast_stack.pop_back();
} |
TOK_IF '(' expr ')' {
@@ -2834,8 +3130,7 @@ gen_block:
ast_stack.push_back(node);
} module_gen_body TOK_END opt_label {
exitTypeScope();
- if ($3 != NULL && $7 != NULL && *$3 != *$7)
- frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $3->c_str()+1, $7->c_str()+1);
+ checkLabelsMatch("Begin label", $3, $7);
delete $3;
delete $7;
SET_AST_NODE_LOC(ast_stack.back(), @1, @7);
diff --git a/guidelines/Checklists b/guidelines/Checklists
new file mode 100644
index 000000000..cc61c7876
--- /dev/null
+++ b/guidelines/Checklists
@@ -0,0 +1,120 @@
+Checklist for adding internal cell types
+========================================
+
+Things to do right away:
+
+ - Add to kernel/celltypes.h (incl. eval() handling for non-mem cells)
+ - Add to InternalCellChecker::check() in kernel/rtlil.cc
+ - Add to techlibs/common/simlib.v
+ - Add to techlibs/common/techmap.v
+
+Things to do after finalizing the cell interface:
+
+ - Add support to kernel/satgen.h for the new cell type
+ - Add to manual/CHAPTER_CellLib.tex (or just add a fixme to the bottom)
+ - Maybe add support to the Verilog backend for dumping such cells as expression
+
+
+
+Checklist for creating Yosys releases
+=====================================
+
+Update the CHANGELOG file:
+
+ cd ~yosys
+ gitk &
+ vi CHANGELOG
+
+
+Update and check documentation:
+
+ cd ~yosys
+ make update-manual
+ make manual
+ - sanity check the figures in the appnotes and presentation
+ - if there are any odd things -> investigate
+ - make cosmetic changes to the .tex files if necessary
+
+ cd ~yosys
+ vi README guidelines/*
+ - is the information provided in those file still up to date
+
+
+Then with default config setting:
+
+ cd ~yosys
+ make vgtest
+
+ cd ~yosys
+ ./yosys -p 'proc; show' tests/simple/fiedler-cooley.v
+ ./yosys -p 'proc; opt; show' tests/simple/fiedler-cooley.v
+ ./yosys -p 'synth; show' tests/simple/fiedler-cooley.v
+ ./yosys -p 'synth_xilinx -top up3down5; show' tests/simple/fiedler-cooley.v
+
+ cd ~yosys/examples/cmos
+ bash testbench.sh
+
+ cd ~yosys/examples/basys3
+ bash run.sh
+
+
+Test building plugins with various of the standard passes:
+
+ yosys-config --build test.so equiv_simple.cc
+ - also check the code examples in guidelines/GettingStarted
+
+
+And if a version of the verific library is currently available:
+
+ cd ~yosys
+ cat frontends/verific/build_amd64.txt
+ - follow instructions
+
+ cd frontends/verific
+ ../../yosys test_navre.ys
+
+
+Finally run all tests with "make config-{clang,gcc,gcc-4.8}":
+
+ cd ~yosys
+ make clean
+ make test
+ make ystests
+ make vloghtb
+ make install
+
+ cd ~yosys-bigsim
+ make clean
+ make full
+
+ cd ~vloghammer
+ make purge gen_issues gen_samples
+ make SYN_LIST="yosys" SIM_LIST="icarus yosim verilator" REPORT_FULL=1 world
+ chromium-browser report.html
+
+
+Release:
+
+ - set YOSYS_VER to x.y.z in Makefile
+ - remove "bumpversion" target from Makefile
+ - update version string in CHANGELOG
+ git commit -am "Yosys x.y.z"
+
+ - push tag to github
+ - post changelog on github
+ - post short release note on reddit
+
+
+Updating the website:
+
+ cd ~yosys
+ make manual
+ make install
+
+ - update pdf files on the website
+
+ cd ~yosys-web
+ make update_cmd
+ make update_show
+ git commit -am update
+ make push
diff --git a/CodeOfConduct b/guidelines/CodeOfConduct
index 4f779977b..92decd3b6 100644
--- a/CodeOfConduct
+++ b/guidelines/CodeOfConduct
@@ -55,9 +55,8 @@ further defined and clarified by project maintainers.
Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported by contacting the project team at clifford@clifford.at (and/or
-cliffordvienna@gmail.com if you think your mail to the other address got
-stuck in the spam filter). All complaints will be reviewed and investigated and
+reported by contacting the project team at contact@yosyshq.com and/or
+claire@clairexen.net. All complaints will be reviewed and investigated and
will result in a response that is deemed necessary and appropriate to the
circumstances. The project team is obligated to maintain confidentiality with
regard to the reporter of an incident. Further details of specific enforcement
diff --git a/guidelines/CodingStyle b/guidelines/CodingStyle
new file mode 100644
index 000000000..d3d3a7134
--- /dev/null
+++ b/guidelines/CodingStyle
@@ -0,0 +1,35 @@
+Coding Style
+============
+
+
+Formatting of code
+------------------
+
+- Yosys code is using tabs for indentation. Tabs are 8 characters.
+
+- A continuation of a statement in the following line is indented by
+ two additional tabs.
+
+- Lines are as long as you want them to be. A good rule of thumb is
+ to break lines at about column 150.
+
+- Opening braces can be put on the same or next line as the statement
+ opening the block (if, switch, for, while, do). Put the opening brace
+ on its own line for larger blocks, especially blocks that contains
+ blank lines.
+
+- Otherwise stick to the Linux Kernel Coding Style:
+ https://www.kernel.org/doc/Documentation/CodingStyle
+
+
+C++ Language
+-------------
+
+Yosys is written in C++11. At the moment only constructs supported by
+gcc 4.8 are allowed in Yosys code. This will change in future releases.
+
+In general Yosys uses "int" instead of "size_t". To avoid compiler
+warnings for implicit type casts, always use "GetSize(foobar)" instead
+of "foobar.size()". (GetSize() is defined in kernel/yosys.h)
+
+Use range-based for loops whenever applicable. \ No newline at end of file
diff --git a/CodingReadme b/guidelines/GettingStarted
index 7d4ded93d..fcc84c153 100644
--- a/CodingReadme
+++ b/guidelines/GettingStarted
@@ -1,10 +1,3 @@
-
-This file contains some very brief documentation on things like programming APIs.
-Also consult the Yosys manual and the section about programming in the presentation.
-(Both can be downloaded as PDF from the yosys webpage.)
-
-
---snip-- only the lines below this mark are included in the yosys manual --snip--
Getting Started
===============
@@ -253,304 +246,4 @@ Notes on the existing codebase
For historical reasons not all parts of Yosys adhere to the current coding
style. When adding code to existing parts of the system, adhere to this guide
-for the new code instead of trying to mimic the style of the surrounding code.
-
-
-
-Coding Style
-============
-
-
-Formatting of code
-------------------
-
-- Yosys code is using tabs for indentation. Tabs are 8 characters.
-
-- A continuation of a statement in the following line is indented by
- two additional tabs.
-
-- Lines are as long as you want them to be. A good rule of thumb is
- to break lines at about column 150.
-
-- Opening braces can be put on the same or next line as the statement
- opening the block (if, switch, for, while, do). Put the opening brace
- on its own line for larger blocks, especially blocks that contains
- blank lines.
-
-- Otherwise stick to the Linux Kernel Coding Style:
- https://www.kernel.org/doc/Documentation/CodingStyle
-
-
-C++ Language
--------------
-
-Yosys is written in C++11. At the moment only constructs supported by
-gcc 4.8 are allowed in Yosys code. This will change in future releases.
-
-In general Yosys uses "int" instead of "size_t". To avoid compiler
-warnings for implicit type casts, always use "GetSize(foobar)" instead
-of "foobar.size()". (GetSize() is defined in kernel/yosys.h)
-
-Use range-based for loops whenever applicable.
-
-
---snap-- only the lines above this mark are included in the yosys manual --snap--
-
-
-Creating the Visual Studio Template Project
-===========================================
-
-1. Create an empty Visual C++ Win32 Console App project
-
- Microsoft Visual Studio Express 2013 for Windows Desktop
- Open New Project Wizard (File -> New Project..)
-
- Project Name: YosysVS
- Solution Name: YosysVS
- [X] Create directory for solution
- [ ] Add to source control
-
- [X] Console applications
- [X] Empty Project
- [ ] SDL checks
-
-2. Open YosysVS Project Properties
-
- Select Configuration: All Configurations
-
- C/C++ -> General -> Additional Include Directories
- Add: ..\yosys
-
- C/C++ -> Preprocessor -> Preprocessor Definitions
- Add: _YOSYS_;_CRT_SECURE_NO_WARNINGS
-
-3. Resulting file system tree:
-
- YosysVS/
- YosysVS/YosysVS
- YosysVS/YosysVS/YosysVS.vcxproj
- YosysVS/YosysVS/YosysVS.vcxproj.filters
- YosysVS/YosysVS.sdf
- YosysVS/YosysVS.sln
- YosysVS/YosysVS.v12.suo
-
-4. Zip YosysVS as YosysVS-Tpl-v1.zip
-
-
-
-Checklist for adding internal cell types
-========================================
-
-Things to do right away:
-
- - Add to kernel/celltypes.h (incl. eval() handling for non-mem cells)
- - Add to InternalCellChecker::check() in kernel/rtlil.cc
- - Add to techlibs/common/simlib.v
- - Add to techlibs/common/techmap.v
-
-Things to do after finalizing the cell interface:
-
- - Add support to kernel/satgen.h for the new cell type
- - Add to manual/CHAPTER_CellLib.tex (or just add a fixme to the bottom)
- - Maybe add support to the Verilog backend for dumping such cells as expression
-
-
-
-Checklist for creating Yosys releases
-=====================================
-
-Update the CHANGELOG file:
-
- cd ~yosys
- gitk &
- vi CHANGELOG
-
-
-Update and check documentation:
-
- cd ~yosys
- make update-manual
- make manual
- - sanity check the figures in the appnotes and presentation
- - if there are any odd things -> investigate
- - make cosmetic changes to the .tex files if necessary
-
- cd ~yosys
- vi README CodingReadme
- - is the information provided in those file still up to date
-
-
-Then with default config setting:
-
- cd ~yosys
- make vgtest
-
- cd ~yosys
- ./yosys -p 'proc; show' tests/simple/fiedler-cooley.v
- ./yosys -p 'proc; opt; show' tests/simple/fiedler-cooley.v
- ./yosys -p 'synth; show' tests/simple/fiedler-cooley.v
- ./yosys -p 'synth_xilinx -top up3down5; show' tests/simple/fiedler-cooley.v
-
- cd ~yosys/examples/cmos
- bash testbench.sh
-
- cd ~yosys/examples/basys3
- bash run.sh
-
-
-Test building plugins with various of the standard passes:
-
- yosys-config --build test.so equiv_simple.cc
- - also check the code examples in CodingReadme
-
-
-And if a version of the verific library is currently available:
-
- cd ~yosys
- cat frontends/verific/build_amd64.txt
- - follow instructions
-
- cd frontends/verific
- ../../yosys test_navre.ys
-
-
-Finally run all tests with "make config-{clang,gcc,gcc-4.8}":
-
- cd ~yosys
- make clean
- make test
- make ystests
- make vloghtb
- make install
-
- cd ~yosys-bigsim
- make clean
- make full
-
- cd ~vloghammer
- make purge gen_issues gen_samples
- make SYN_LIST="yosys" SIM_LIST="icarus yosim verilator" REPORT_FULL=1 world
- chromium-browser report.html
-
-
-Release:
-
- - set YOSYS_VER to x.y.z in Makefile
- - remove "bumpversion" target from Makefile
- - update version string in CHANGELOG
- git commit -am "Yosys x.y.z"
-
- - push tag to github
- - post changelog on github
- - post short release note on reddit
-
-
-Updating the website:
-
- cd ~yosys
- make manual
- make install
-
- - update pdf files on the website
-
- cd ~yosys-web
- make update_cmd
- make update_show
- 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
-```
+for the new code instead of trying to mimic the style of the surrounding code. \ No newline at end of file
diff --git a/guidelines/UnitTests b/guidelines/UnitTests
new file mode 100644
index 000000000..d42a63ce5
--- /dev/null
+++ b/guidelines/UnitTests
@@ -0,0 +1,69 @@
+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/guidelines/Windows b/guidelines/Windows
new file mode 100644
index 000000000..2af0620fa
--- /dev/null
+++ b/guidelines/Windows
@@ -0,0 +1,83 @@
+Creating the Visual Studio Template Project
+===========================================
+
+1. Create an empty Visual C++ Win32 Console App project
+
+ Microsoft Visual Studio Express 2013 for Windows Desktop
+ Open New Project Wizard (File -> New Project..)
+
+ Project Name: YosysVS
+ Solution Name: YosysVS
+ [X] Create directory for solution
+ [ ] Add to source control
+
+ [X] Console applications
+ [X] Empty Project
+ [ ] SDL checks
+
+2. Open YosysVS Project Properties
+
+ Select Configuration: All Configurations
+
+ C/C++ -> General -> Additional Include Directories
+ Add: ..\yosys
+
+ C/C++ -> Preprocessor -> Preprocessor Definitions
+ Add: _YOSYS_;_CRT_SECURE_NO_WARNINGS
+
+3. Resulting file system tree:
+
+ YosysVS/
+ YosysVS/YosysVS
+ YosysVS/YosysVS/YosysVS.vcxproj
+ YosysVS/YosysVS/YosysVS.vcxproj.filters
+ YosysVS/YosysVS.sdf
+ YosysVS/YosysVS.sln
+ YosysVS/YosysVS.v12.suo
+
+4. Zip YosysVS as YosysVS-Tpl-v1.zip
+
+Compiling with Visual Studio
+============================
+
+Visual Studio builds are not directly supported by build scripts, but they are still possible.
+
+1. Easy way
+
+ - Go to https://github.com/YosysHQ/yosys/actions/workflows/vs.yml?query=branch%3Amaster
+ - Click on the most recent completed run
+ - In Artifacts region find vcxsrc and click on it to download
+ - Unpack downloaded ZIP file
+ - Open YosysVS.sln with Visual Studio
+
+2. Using WSL or MSYS2
+
+ - Make sure to have make, python3 and git available
+ - Git clone yosys repository
+ - Execute ```make vcxsrc YOSYS_VER=latest```
+ - File yosys-win32-vcxsrc-latest.zip will be created
+ - Transfer that file to location visible by Windows application
+ - Unpack ZIP
+ - Open YosysVS.sln with Visual Studio
+
+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/YosysHQ/yosys.git yosys-win32
+ cd yosys-win32
+ make config-mxe
+ make -j$(nproc) mxebin
diff --git a/kernel/binding.cc b/kernel/binding.cc
new file mode 100644
index 000000000..621f7007b
--- /dev/null
+++ b/kernel/binding.cc
@@ -0,0 +1,29 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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 "binding.h"
+
+YOSYS_NAMESPACE_BEGIN
+
+RTLIL::Binding::Binding(RTLIL::IdString target_type,
+ RTLIL::IdString target_name)
+ : target_type(target_type), target_name(target_name)
+{}
+
+YOSYS_NAMESPACE_END
diff --git a/kernel/binding.h b/kernel/binding.h
new file mode 100644
index 000000000..3b64e76da
--- /dev/null
+++ b/kernel/binding.h
@@ -0,0 +1,60 @@
+/* -*- c++ -*-
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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.
+ *
+ */
+
+#ifndef BINDING_H
+#define BINDING_H
+
+#include "kernel/rtlil.h"
+
+YOSYS_NAMESPACE_BEGIN
+
+struct RTLIL::Binding
+{
+ // Represents a bind construct.
+ //
+ // The target of the binding is represented by target_type and
+ // target_name (see comments above the fields).
+
+ Binding(RTLIL::IdString target_type,
+ RTLIL::IdString target_name);
+
+ virtual ~Binding() {}
+
+ // Return a string describing the binding
+ virtual std::string describe() const = 0;
+
+protected:
+ // May be empty. If not, it's the name of the module or interface to
+ // bind to.
+ RTLIL::IdString target_type;
+
+ // If target_type is nonempty (the usual case), this is a hierarchical
+ // reference to the bind target. If target_type is empty, we have to
+ // wait until the hierarchy pass to figure out whether this was the name
+ // of a module/interface type or an instance.
+ RTLIL::IdString target_name;
+
+ // An attribute name which contains an ID that's unique across binding
+ // instances (used to ensure we don't apply a binding twice to a module)
+ RTLIL::IdString attr_name;
+};
+
+YOSYS_NAMESPACE_END
+
+#endif
diff --git a/kernel/bitpattern.h b/kernel/bitpattern.h
index 894a95ed1..7a8eb39f9 100644
--- a/kernel/bitpattern.h
+++ b/kernel/bitpattern.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/kernel/calc.cc b/kernel/calc.cc
index d54ccbc10..0865db526 100644
--- a/kernel/calc.cc
+++ b/kernel/calc.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -609,5 +609,56 @@ RTLIL::Const RTLIL::const_neg(const RTLIL::Const &arg1, const RTLIL::Const&, boo
return RTLIL::const_sub(zero, arg1_ext, true, signed1, result_len);
}
+RTLIL::Const RTLIL::const_bmux(const RTLIL::Const &arg1, const RTLIL::Const &arg2)
+{
+ std::vector<RTLIL::State> t = arg1.bits;
+
+ for (int i = GetSize(arg2)-1; i >= 0; i--)
+ {
+ RTLIL::State sel = arg2.bits.at(i);
+ std::vector<RTLIL::State> new_t;
+ if (sel == State::S0)
+ new_t = std::vector<RTLIL::State>(t.begin(), t.begin() + GetSize(t)/2);
+ else if (sel == State::S1)
+ new_t = std::vector<RTLIL::State>(t.begin() + GetSize(t)/2, t.end());
+ else
+ for (int j = 0; j < GetSize(t)/2; j++)
+ new_t.push_back(t[j] == t[j + GetSize(t)/2] ? t[j] : RTLIL::Sx);
+ t.swap(new_t);
+ }
+
+ return t;
+}
+
+RTLIL::Const RTLIL::const_demux(const RTLIL::Const &arg1, const RTLIL::Const &arg2)
+{
+ int width = GetSize(arg1);
+ int s_width = GetSize(arg2);
+ std::vector<RTLIL::State> res;
+ for (int i = 0; i < (1 << s_width); i++)
+ {
+ bool ne = false;
+ bool x = false;
+ for (int j = 0; j < s_width; j++) {
+ bool bit = i & 1 << j;
+ if (arg2[j] == (bit ? RTLIL::S0 : RTLIL::S1))
+ ne = true;
+ else if (arg2[j] != RTLIL::S0 && arg2[j] != RTLIL::S1)
+ x = true;
+ }
+ if (ne) {
+ for (int j = 0; j < width; j++)
+ res.push_back(State::S0);
+ } else if (x) {
+ for (int j = 0; j < width; j++)
+ res.push_back(arg1.bits[j] == State::S0 ? State::S0 : State::Sx);
+ } else {
+ for (int j = 0; j < width; j++)
+ res.push_back(arg1.bits[j]);
+ }
+ }
+ return res;
+}
+
YOSYS_NAMESPACE_END
diff --git a/kernel/cellaigs.cc b/kernel/cellaigs.cc
index 2c82b1bca..292af3f51 100644
--- a/kernel/cellaigs.cc
+++ b/kernel/cellaigs.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/kernel/cellaigs.h b/kernel/cellaigs.h
index 1417a614c..8f6d69ba6 100644
--- a/kernel/cellaigs.h
+++ b/kernel/cellaigs.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/kernel/celledges.cc b/kernel/celledges.cc
index 314e7c77e..c43ba8db3 100644
--- a/kernel/celledges.cc
+++ b/kernel/celledges.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -142,6 +142,36 @@ void mux_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
}
}
+void bmux_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
+{
+ int width = GetSize(cell->getPort(ID::Y));
+ int a_width = GetSize(cell->getPort(ID::A));
+ int s_width = GetSize(cell->getPort(ID::S));
+
+ for (int i = 0; i < width; i++)
+ {
+ for (int k = i; k < a_width; k += width)
+ db->add_edge(cell, ID::A, k, ID::Y, i, -1);
+
+ for (int k = 0; k < s_width; k++)
+ db->add_edge(cell, ID::S, k, ID::Y, i, -1);
+ }
+}
+
+void demux_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
+{
+ int width = GetSize(cell->getPort(ID::Y));
+ int a_width = GetSize(cell->getPort(ID::A));
+ int s_width = GetSize(cell->getPort(ID::S));
+
+ for (int i = 0; i < width; i++)
+ {
+ db->add_edge(cell, ID::A, i % a_width, ID::Y, i, -1);
+ for (int k = 0; k < s_width; k++)
+ db->add_edge(cell, ID::S, k, ID::Y, i, -1);
+ }
+}
+
PRIVATE_NAMESPACE_END
bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL::Cell *cell)
@@ -187,6 +217,16 @@ bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL
return true;
}
+ if (cell->type == ID($bmux)) {
+ bmux_op(this, cell);
+ return true;
+ }
+
+ if (cell->type == ID($demux)) {
+ demux_op(this, cell);
+ return true;
+ }
+
// FIXME: $mul $div $mod $divfloor $modfloor $slice $concat
// FIXME: $lut $sop $alu $lcu $macc $fa
diff --git a/kernel/celledges.h b/kernel/celledges.h
index d105e4009..d5e374f05 100644
--- a/kernel/celledges.h
+++ b/kernel/celledges.h
@@ -1,7 +1,7 @@
/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/kernel/celltypes.h b/kernel/celltypes.h
index 944cb301a..7e9cfb38d 100644
--- a/kernel/celltypes.h
+++ b/kernel/celltypes.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -127,6 +127,9 @@ struct CellTypes
for (auto type : std::vector<RTLIL::IdString>({ID($mux), ID($pmux)}))
setup_type(type, {ID::A, ID::B, ID::S}, {ID::Y}, true);
+ for (auto type : std::vector<RTLIL::IdString>({ID($bmux), ID($demux)}))
+ setup_type(type, {ID::A, ID::S}, {ID::Y}, true);
+
setup_type(ID($lcu), {ID::P, ID::G, ID::CI}, {ID::CO}, true);
setup_type(ID($alu), {ID::A, ID::B, ID::CI, ID::BI}, {ID::X, ID::Y, ID::CO}, true);
setup_type(ID($fa), {ID::A, ID::B, ID::C}, {ID::X, ID::Y}, true);
@@ -142,6 +145,8 @@ struct CellTypes
setup_type(ID($dffsre), {ID::CLK, ID::SET, ID::CLR, ID::D, ID::EN}, {ID::Q});
setup_type(ID($adff), {ID::CLK, ID::ARST, ID::D}, {ID::Q});
setup_type(ID($adffe), {ID::CLK, ID::ARST, ID::D, ID::EN}, {ID::Q});
+ setup_type(ID($aldff), {ID::CLK, ID::ALOAD, ID::AD, ID::D}, {ID::Q});
+ setup_type(ID($aldffe), {ID::CLK, ID::ALOAD, ID::AD, ID::D, ID::EN}, {ID::Q});
setup_type(ID($sdff), {ID::CLK, ID::SRST, ID::D}, {ID::Q});
setup_type(ID($sdffe), {ID::CLK, ID::SRST, ID::D, ID::EN}, {ID::Q});
setup_type(ID($sdffce), {ID::CLK, ID::SRST, ID::D, ID::EN}, {ID::Q});
@@ -155,9 +160,13 @@ struct CellTypes
setup_internals_ff();
setup_type(ID($memrd), {ID::CLK, ID::EN, ID::ADDR}, {ID::DATA});
+ setup_type(ID($memrd_v2), {ID::CLK, ID::EN, ID::ARST, ID::SRST, ID::ADDR}, {ID::DATA});
setup_type(ID($memwr), {ID::CLK, ID::EN, ID::ADDR, ID::DATA}, pool<RTLIL::IdString>());
+ setup_type(ID($memwr_v2), {ID::CLK, ID::EN, ID::ADDR, ID::DATA}, pool<RTLIL::IdString>());
setup_type(ID($meminit), {ID::ADDR, ID::DATA}, pool<RTLIL::IdString>());
+ setup_type(ID($meminit_v2), {ID::ADDR, ID::DATA, ID::EN}, pool<RTLIL::IdString>());
setup_type(ID($mem), {ID::RD_CLK, ID::RD_EN, ID::RD_ADDR, ID::WR_CLK, ID::WR_EN, ID::WR_ADDR, ID::WR_DATA}, {ID::RD_DATA});
+ setup_type(ID($mem_v2), {ID::RD_CLK, ID::RD_EN, ID::RD_ARST, ID::RD_SRST, ID::RD_ADDR, ID::WR_CLK, ID::WR_EN, ID::WR_ADDR, ID::WR_DATA}, {ID::RD_DATA});
setup_type(ID($fsm), {ID::CLK, ID::ARST, ID::CTRL_IN}, {ID::CTRL_OUT});
}
@@ -222,6 +231,15 @@ struct CellTypes
for (auto c1 : list_np)
for (auto c2 : list_np)
+ setup_type(stringf("$_ALDFF_%c%c_", c1, c2), {ID::C, ID::L, ID::AD, ID::D}, {ID::Q});
+
+ for (auto c1 : list_np)
+ for (auto c2 : list_np)
+ for (auto c3 : list_np)
+ setup_type(stringf("$_ALDFFE_%c%c%c_", c1, c2, c3), {ID::C, ID::L, ID::AD, ID::D, ID::E}, {ID::Q});
+
+ for (auto c1 : list_np)
+ for (auto c2 : list_np)
for (auto c3 : list_np)
setup_type(stringf("$_DFFSR_%c%c%c_", c1, c2, c3), {ID::C, ID::S, ID::R, ID::D}, {ID::Q});
@@ -396,6 +414,16 @@ struct CellTypes
return ret;
}
+ if (cell->type == ID($bmux))
+ {
+ return const_bmux(arg1, arg2);
+ }
+
+ if (cell->type == ID($demux))
+ {
+ return const_demux(arg1, arg2);
+ }
+
if (cell->type == ID($lut))
{
int width = cell->parameters.at(ID::WIDTH).as_int();
@@ -405,21 +433,7 @@ struct CellTypes
t.push_back(State::S0);
t.resize(1 << width);
- for (int i = width-1; i >= 0; i--) {
- RTLIL::State sel = arg1.bits.at(i);
- std::vector<RTLIL::State> new_t;
- if (sel == State::S0)
- new_t = std::vector<RTLIL::State>(t.begin(), t.begin() + GetSize(t)/2);
- else if (sel == State::S1)
- new_t = std::vector<RTLIL::State>(t.begin() + GetSize(t)/2, t.end());
- else
- for (int j = 0; j < GetSize(t)/2; j++)
- new_t.push_back(t[j] == t[j + GetSize(t)/2] ? t[j] : RTLIL::Sx);
- t.swap(new_t);
- }
-
- log_assert(GetSize(t) == 1);
- return t;
+ return const_bmux(t, arg1);
}
if (cell->type == ID($sop))
diff --git a/kernel/consteval.h b/kernel/consteval.h
index ff8cf86d6..642eb42b2 100644
--- a/kernel/consteval.h
+++ b/kernel/consteval.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -135,8 +135,6 @@ struct ConstEval
if (cell->hasPort(ID::S)) {
sig_s = cell->getPort(ID::S);
- if (!eval(sig_s, undef, cell))
- return false;
}
if (cell->hasPort(ID::A))
@@ -151,6 +149,9 @@ struct ConstEval
int count_maybe_set_s_bits = 0;
int count_set_s_bits = 0;
+ if (!eval(sig_s, undef, cell))
+ return false;
+
for (int i = 0; i < sig_s.size(); i++)
{
RTLIL::State s_bit = sig_s.extract(i, 1).as_const().bits.at(0);
@@ -198,6 +199,36 @@ struct ConstEval
else
set(sig_y, y_values.front());
}
+ else if (cell->type == ID($bmux))
+ {
+ if (!eval(sig_s, undef, cell))
+ return false;
+
+ if (sig_s.is_fully_def()) {
+ int sel = sig_s.as_int();
+ int width = GetSize(sig_y);
+ SigSpec res = sig_a.extract(sel * width, width);
+ if (!eval(res, undef, cell))
+ return false;
+ set(sig_y, res.as_const());
+ } else {
+ if (!eval(sig_a, undef, cell))
+ return false;
+ set(sig_y, const_bmux(sig_a.as_const(), sig_s.as_const()));
+ }
+ }
+ else if (cell->type == ID($demux))
+ {
+ if (!eval(sig_a, undef, cell))
+ return false;
+ if (sig_a.is_fully_zero()) {
+ set(sig_y, Const(0, GetSize(sig_y)));
+ } else {
+ if (!eval(sig_s, undef, cell))
+ return false;
+ set(sig_y, const_demux(sig_a.as_const(), sig_s.as_const()));
+ }
+ }
else if (cell->type == ID($fa))
{
RTLIL::SigSpec sig_c = cell->getPort(ID::C);
diff --git a/kernel/constids.inc b/kernel/constids.inc
index 3c2ff9beb..566b76217 100644
--- a/kernel/constids.inc
+++ b/kernel/constids.inc
@@ -11,9 +11,12 @@ X(abc9_mergeability)
X(abc9_scc_id)
X(abcgroup)
X(ABITS)
+X(AD)
X(ADDR)
X(allconst)
X(allseq)
+X(ALOAD)
+X(ALOAD_POLARITY)
X(always_comb)
X(always_ff)
X(always_latch)
@@ -32,6 +35,7 @@ X(bugpoint_keep)
X(B_WIDTH)
X(C)
X(cells_not_processed)
+X(CE_OVER_SRST)
X(CFG_ABITS)
X(CFG_DBITS)
X(CFG_INIT)
@@ -46,6 +50,7 @@ X(CLK_POLARITY)
X(CLR)
X(CLR_POLARITY)
X(CO)
+X(COLLISION_X_MASK)
X(CONFIG)
X(CONFIG_WIDTH)
X(CTRL_IN)
@@ -95,6 +100,7 @@ X(hdlname)
X(hierconn)
X(I)
X(INIT)
+X(INIT_VALUE)
X(init)
X(initial_top)
X(interface_modport)
@@ -133,19 +139,31 @@ X(onehot)
X(P)
X(parallel_case)
X(parameter)
+X(PORTID)
X(PRIORITY)
+X(PRIORITY_MASK)
X(Q)
X(qwp_position)
X(R)
X(RD_ADDR)
+X(RD_ARST)
+X(RD_ARST_VALUE)
+X(RD_CE_OVER_SRST)
X(RD_CLK)
X(RD_CLK_ENABLE)
X(RD_CLK_POLARITY)
+X(RD_COLLISION_X_MASK)
X(RD_DATA)
X(RD_EN)
+X(RD_INIT_VALUE)
X(RD_PORTS)
+X(RD_SRST)
+X(RD_SRST_VALUE)
+X(RD_TRANSPARENCY_MASK)
X(RD_TRANSPARENT)
+X(RD_WIDE_CONTINUATION)
X(reg)
+X(reprocess_after)
X(S)
X(SET)
X(SET_POLARITY)
@@ -161,6 +179,7 @@ X(SRC_WIDTH)
X(SRST)
X(SRST_POLARITY)
X(SRST_VALUE)
+X(sta_arrival)
X(STATE_BITS)
X(STATE_NUM)
X(STATE_NUM_LOG2)
@@ -195,6 +214,7 @@ X(T_LIMIT_TYP)
X(to_delete)
X(top)
X(TRANS_NUM)
+X(TRANSPARENCY_MASK)
X(TRANSPARENT)
X(TRANS_TABLE)
X(T_RISE_MAX)
@@ -220,6 +240,8 @@ X(WR_CLK_POLARITY)
X(WR_DATA)
X(WR_EN)
X(WR_PORTS)
+X(WR_PRIORITY_MASK)
+X(WR_WIDE_CONTINUATION)
X(X)
X(Y)
X(Y_WIDTH)
diff --git a/kernel/cost.h b/kernel/cost.h
index ea2a4c1f0..b81420af7 100644
--- a/kernel/cost.h
+++ b/kernel/cost.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/kernel/driver.cc b/kernel/driver.cc
index b55f02837..f8f940e89 100644
--- a/kernel/driver.cc
+++ b/kernel/driver.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -118,7 +118,7 @@ int main(int argc, char **argv)
if (argc == 2)
{
// Run the first argument as a script file
- run_frontend(argv[1], "script", 0, 0, 0);
+ run_frontend(argv[1], "script");
}
}
@@ -202,12 +202,13 @@ int main(int argc, char **argv)
std::string output_filename = "";
std::string scriptfile = "";
std::string depsfile = "";
+ std::string topmodule = "";
bool scriptfile_tcl = false;
- bool got_output_filename = false;
bool print_banner = true;
bool print_stats = true;
bool call_abort = false;
bool timing_details = false;
+ bool run_shell = true;
bool mode_v = false;
bool mode_q = false;
@@ -288,6 +289,9 @@ int main(int argc, char **argv)
printf(" -A\n");
printf(" will call abort() at the end of the script. for debugging\n");
printf("\n");
+ printf(" -r <module_name>\n");
+ printf(" elaborate command line arguments using the specified top module\n");
+ printf("\n");
printf(" -D <macro>[=<value>]\n");
printf(" set the specified Verilog define (via \"read -define\")\n");
printf("\n");
@@ -342,7 +346,7 @@ int main(int argc, char **argv)
}
int opt;
- while ((opt = getopt(argc, argv, "MXAQTVSgm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:D:P:E:x:")) != -1)
+ while ((opt = getopt(argc, argv, "MXAQTVSgm:f:Hh:b:o:p:l:L:qv:tds:c:W:w:e:r:D:P:E:x:")) != -1)
{
switch (opt)
{
@@ -366,6 +370,7 @@ int main(int argc, char **argv)
exit(0);
case 'S':
passes_commands.push_back("synth");
+ run_shell = false;
break;
case 'g':
log_force_debug++;
@@ -378,19 +383,23 @@ int main(int argc, char **argv)
break;
case 'H':
passes_commands.push_back("help");
+ run_shell = false;
break;
case 'h':
passes_commands.push_back(stringf("help %s", optarg));
+ run_shell = false;
break;
case 'b':
backend_command = optarg;
+ run_shell = false;
break;
case 'p':
passes_commands.push_back(optarg);
+ run_shell = false;
break;
case 'o':
output_filename = optarg;
- got_output_filename = true;
+ run_shell = false;
break;
case 'l':
case 'L':
@@ -422,10 +431,12 @@ int main(int argc, char **argv)
case 's':
scriptfile = optarg;
scriptfile_tcl = false;
+ run_shell = false;
break;
case 'c':
scriptfile = optarg;
scriptfile_tcl = true;
+ run_shell = false;
break;
case 'W':
log_warn_regexes.push_back(YS_REGEX_COMPILE(optarg));
@@ -436,6 +447,9 @@ int main(int argc, char **argv)
case 'e':
log_werror_regexes.push_back(YS_REGEX_COMPILE(optarg));
break;
+ case 'r':
+ topmodule = optarg;
+ break;
case 'D':
vlog_defines.push_back(optarg);
break;
@@ -506,12 +520,6 @@ int main(int argc, char **argv)
for (auto &fn : plugin_filenames)
load_plugin(fn, {});
- if (optind == argc && passes_commands.size() == 0 && scriptfile.empty()) {
- if (!got_output_filename)
- backend_command = "";
- shell(yosys_design);
- }
-
if (!vlog_defines.empty()) {
std::string vdef_cmd = "read -define";
for (auto vdef : vlog_defines)
@@ -520,7 +528,11 @@ int main(int argc, char **argv)
}
while (optind < argc)
- run_frontend(argv[optind++], frontend_command, output_filename == "-" ? &backend_command : NULL);
+ if (run_frontend(argv[optind++], frontend_command))
+ run_shell = false;
+
+ if (!topmodule.empty())
+ run_pass("hierarchy -top " + topmodule);
if (!scriptfile.empty()) {
if (scriptfile_tcl) {
@@ -531,13 +543,15 @@ int main(int argc, char **argv)
log_error("Can't exectue TCL script: this version of yosys is not built with TCL support enabled.\n");
#endif
} else
- run_frontend(scriptfile, "script", output_filename == "-" ? &backend_command : NULL);
+ run_frontend(scriptfile, "script");
}
for (auto it = passes_commands.begin(); it != passes_commands.end(); it++)
run_pass(*it);
- if (!backend_command.empty())
+ if (run_shell)
+ shell(yosys_design);
+ else
run_backend(output_filename, backend_command);
yosys_design->check();
diff --git a/kernel/ff.cc b/kernel/ff.cc
new file mode 100644
index 000000000..c43482bd2
--- /dev/null
+++ b/kernel/ff.cc
@@ -0,0 +1,755 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2020 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * 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/ff.h"
+
+USING_YOSYS_NAMESPACE
+
+FfData::FfData(FfInitVals *initvals, Cell *cell_) : FfData(cell_->module, initvals, cell_->name)
+{
+ cell = cell_;
+ sig_q = cell->getPort(ID::Q);
+ width = GetSize(sig_q);
+ attributes = cell->attributes;
+
+ if (initvals)
+ val_init = (*initvals)(sig_q);
+
+ std::string type_str = cell->type.str();
+
+ if (cell->type.in(ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($sdff), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch), ID($dlatchsr), ID($sr))) {
+ if (cell->type == ID($ff)) {
+ has_gclk = true;
+ sig_d = cell->getPort(ID::D);
+ } else if (cell->type == ID($sr)) {
+ // No data input at all.
+ } else if (cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr))) {
+ has_aload = true;
+ sig_aload = cell->getPort(ID::EN);
+ pol_aload = cell->getParam(ID::EN_POLARITY).as_bool();
+ sig_ad = cell->getPort(ID::D);
+ } else {
+ has_clk = true;
+ sig_clk = cell->getPort(ID::CLK);
+ pol_clk = cell->getParam(ID::CLK_POLARITY).as_bool();
+ sig_d = cell->getPort(ID::D);
+ }
+ if (cell->type.in(ID($dffe), ID($dffsre), ID($adffe), ID($aldffe), ID($sdffe), ID($sdffce))) {
+ has_ce = true;
+ sig_ce = cell->getPort(ID::EN);
+ pol_ce = cell->getParam(ID::EN_POLARITY).as_bool();
+ }
+ if (cell->type.in(ID($dffsr), ID($dffsre), ID($dlatchsr), ID($sr))) {
+ has_sr = true;
+ sig_clr = cell->getPort(ID::CLR);
+ sig_set = cell->getPort(ID::SET);
+ pol_clr = cell->getParam(ID::CLR_POLARITY).as_bool();
+ pol_set = cell->getParam(ID::SET_POLARITY).as_bool();
+ }
+ if (cell->type.in(ID($aldff), ID($aldffe))) {
+ has_aload = true;
+ sig_aload = cell->getPort(ID::ALOAD);
+ pol_aload = cell->getParam(ID::ALOAD_POLARITY).as_bool();
+ sig_ad = cell->getPort(ID::AD);
+ }
+ if (cell->type.in(ID($adff), ID($adffe), ID($adlatch))) {
+ has_arst = true;
+ sig_arst = cell->getPort(ID::ARST);
+ pol_arst = cell->getParam(ID::ARST_POLARITY).as_bool();
+ val_arst = cell->getParam(ID::ARST_VALUE);
+ }
+ if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce))) {
+ has_srst = true;
+ sig_srst = cell->getPort(ID::SRST);
+ pol_srst = cell->getParam(ID::SRST_POLARITY).as_bool();
+ val_srst = cell->getParam(ID::SRST_VALUE);
+ ce_over_srst = cell->type == ID($sdffce);
+ }
+ } else if (cell->type == ID($_FF_)) {
+ is_fine = true;
+ has_gclk = true;
+ sig_d = cell->getPort(ID::D);
+ } else if (type_str.substr(0, 5) == "$_SR_") {
+ is_fine = true;
+ has_sr = true;
+ pol_set = type_str[5] == 'P';
+ pol_clr = type_str[6] == 'P';
+ sig_set = cell->getPort(ID::S);
+ sig_clr = cell->getPort(ID::R);
+ } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 8) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[6] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 10) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[7] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_ce = true;
+ pol_ce = type_str[8] == 'P';
+ sig_ce = cell->getPort(ID::E);
+ } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 10) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[6] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_arst = true;
+ pol_arst = type_str[7] == 'P';
+ sig_arst = cell->getPort(ID::R);
+ val_arst = type_str[8] == '1' ? State::S1 : State::S0;
+ } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 12) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[7] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_arst = true;
+ pol_arst = type_str[8] == 'P';
+ sig_arst = cell->getPort(ID::R);
+ val_arst = type_str[9] == '1' ? State::S1 : State::S0;
+ has_ce = true;
+ pol_ce = type_str[10] == 'P';
+ sig_ce = cell->getPort(ID::E);
+ } else if (type_str.substr(0, 8) == "$_ALDFF_" && type_str.size() == 11) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[8] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_aload = true;
+ pol_aload = type_str[9] == 'P';
+ sig_aload = cell->getPort(ID::L);
+ sig_ad = cell->getPort(ID::AD);
+ } else if (type_str.substr(0, 9) == "$_ALDFFE_" && type_str.size() == 13) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[9] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_aload = true;
+ pol_aload = type_str[10] == 'P';
+ sig_aload = cell->getPort(ID::L);
+ sig_ad = cell->getPort(ID::AD);
+ has_ce = true;
+ pol_ce = type_str[11] == 'P';
+ sig_ce = cell->getPort(ID::E);
+ } else if (type_str.substr(0, 8) == "$_DFFSR_" && type_str.size() == 12) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[8] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_sr = true;
+ pol_set = type_str[9] == 'P';
+ pol_clr = type_str[10] == 'P';
+ sig_set = cell->getPort(ID::S);
+ sig_clr = cell->getPort(ID::R);
+ } else if (type_str.substr(0, 9) == "$_DFFSRE_" && type_str.size() == 14) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[9] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_sr = true;
+ pol_set = type_str[10] == 'P';
+ pol_clr = type_str[11] == 'P';
+ sig_set = cell->getPort(ID::S);
+ sig_clr = cell->getPort(ID::R);
+ has_ce = true;
+ pol_ce = type_str[12] == 'P';
+ sig_ce = cell->getPort(ID::E);
+ } else if (type_str.substr(0, 7) == "$_SDFF_" && type_str.size() == 11) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[7] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_srst = true;
+ pol_srst = type_str[8] == 'P';
+ sig_srst = cell->getPort(ID::R);
+ val_srst = type_str[9] == '1' ? State::S1 : State::S0;
+ } else if (type_str.substr(0, 8) == "$_SDFFE_" && type_str.size() == 13) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[8] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_srst = true;
+ pol_srst = type_str[9] == 'P';
+ sig_srst = cell->getPort(ID::R);
+ val_srst = type_str[10] == '1' ? State::S1 : State::S0;
+ has_ce = true;
+ pol_ce = type_str[11] == 'P';
+ sig_ce = cell->getPort(ID::E);
+ } else if (type_str.substr(0, 9) == "$_SDFFCE_" && type_str.size() == 14) {
+ is_fine = true;
+ sig_d = cell->getPort(ID::D);
+ has_clk = true;
+ pol_clk = type_str[9] == 'P';
+ sig_clk = cell->getPort(ID::C);
+ has_srst = true;
+ pol_srst = type_str[10] == 'P';
+ sig_srst = cell->getPort(ID::R);
+ val_srst = type_str[11] == '1' ? State::S1 : State::S0;
+ has_ce = true;
+ pol_ce = type_str[12] == 'P';
+ sig_ce = cell->getPort(ID::E);
+ ce_over_srst = true;
+ } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 11) {
+ is_fine = true;
+ has_aload = true;
+ sig_ad = cell->getPort(ID::D);
+ has_aload = true;
+ pol_aload = type_str[9] == 'P';
+ sig_aload = cell->getPort(ID::E);
+ } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 13) {
+ is_fine = true;
+ has_aload = true;
+ sig_ad = cell->getPort(ID::D);
+ has_aload = true;
+ pol_aload = type_str[9] == 'P';
+ sig_aload = cell->getPort(ID::E);
+ has_arst = true;
+ pol_arst = type_str[10] == 'P';
+ sig_arst = cell->getPort(ID::R);
+ val_arst = type_str[11] == '1' ? State::S1 : State::S0;
+ } else if (type_str.substr(0, 11) == "$_DLATCHSR_" && type_str.size() == 15) {
+ is_fine = true;
+ has_aload = true;
+ sig_ad = cell->getPort(ID::D);
+ has_aload = true;
+ pol_aload = type_str[11] == 'P';
+ sig_aload = cell->getPort(ID::E);
+ has_sr = true;
+ pol_set = type_str[12] == 'P';
+ pol_clr = type_str[13] == 'P';
+ sig_set = cell->getPort(ID::S);
+ sig_clr = cell->getPort(ID::R);
+ } else {
+ log_assert(0);
+ }
+ if (has_aload && !has_clk && !has_sr && !has_arst && sig_ad.is_fully_const()) {
+ // Plain D latches with const D treated specially.
+ has_aload = false;
+ has_arst = true;
+ sig_arst = sig_aload;
+ pol_arst = pol_aload;
+ val_arst = sig_ad.as_const();
+ }
+}
+
+FfData FfData::slice(const std::vector<int> &bits) {
+ FfData res(module, initvals, NEW_ID);
+ res.sig_clk = sig_clk;
+ res.sig_ce = sig_ce;
+ res.sig_aload = sig_aload;
+ res.sig_arst = sig_arst;
+ res.sig_srst = sig_srst;
+ res.has_clk = has_clk;
+ res.has_gclk = has_gclk;
+ res.has_ce = has_ce;
+ res.has_aload = has_aload;
+ res.has_arst = has_arst;
+ res.has_srst = has_srst;
+ res.has_sr = has_sr;
+ res.ce_over_srst = ce_over_srst;
+ res.is_fine = is_fine;
+ res.pol_clk = pol_clk;
+ res.pol_ce = pol_ce;
+ res.pol_aload = pol_aload;
+ res.pol_arst = pol_arst;
+ res.pol_srst = pol_srst;
+ res.pol_clr = pol_clr;
+ res.pol_set = pol_set;
+ res.attributes = attributes;
+ for (int i : bits) {
+ res.sig_q.append(sig_q[i]);
+ if (has_clk || has_gclk)
+ res.sig_d.append(sig_d[i]);
+ if (has_aload)
+ res.sig_ad.append(sig_ad[i]);
+ if (has_sr) {
+ res.sig_clr.append(sig_clr[i]);
+ res.sig_set.append(sig_set[i]);
+ }
+ if (has_arst)
+ res.val_arst.bits.push_back(val_arst[i]);
+ if (has_srst)
+ res.val_srst.bits.push_back(val_srst[i]);
+ if (initvals)
+ res.val_init.bits.push_back(val_init[i]);
+ }
+ res.width = GetSize(res.sig_q);
+ return res;
+}
+
+void FfData::add_dummy_ce() {
+ if (has_ce)
+ return;
+ has_ce = true;
+ pol_ce = true;
+ sig_ce = State::S1;
+ ce_over_srst = false;
+}
+
+void FfData::add_dummy_srst() {
+ if (has_srst)
+ return;
+ has_srst = true;
+ pol_srst = true;
+ sig_srst = State::S0;
+ val_srst = Const(State::Sx, width);
+ ce_over_srst = false;
+}
+
+void FfData::add_dummy_arst() {
+ if (has_arst)
+ return;
+ has_arst = true;
+ pol_arst = true;
+ sig_arst = State::S0;
+ val_arst = Const(State::Sx, width);
+}
+
+void FfData::add_dummy_aload() {
+ if (has_aload)
+ return;
+ has_aload = true;
+ pol_aload = true;
+ sig_aload = State::S0;
+ sig_ad = Const(State::Sx, width);
+}
+
+void FfData::add_dummy_sr() {
+ if (has_sr)
+ return;
+ has_sr = true;
+ pol_clr = true;
+ pol_set = true;
+ sig_clr = Const(State::S0, width);
+ sig_set = Const(State::S0, width);
+}
+
+void FfData::add_dummy_clk() {
+ if (has_clk)
+ return;
+ has_clk = true;
+ pol_clk = true;
+ sig_clk = State::S0;
+ sig_d = Const(State::Sx, width);
+}
+
+void FfData::arst_to_aload() {
+ log_assert(has_arst);
+ log_assert(!has_aload);
+ pol_aload = pol_arst;
+ sig_aload = sig_arst;
+ sig_ad = val_arst;
+ has_aload = true;
+ has_arst = false;
+}
+
+void FfData::arst_to_sr() {
+ log_assert(has_arst);
+ log_assert(!has_sr);
+ pol_clr = pol_arst;
+ pol_set = pol_arst;
+ sig_clr = Const(pol_arst ? State::S0 : State::S1, width);
+ sig_set = Const(pol_arst ? State::S0 : State::S1, width);
+ has_sr = true;
+ has_arst = false;
+ for (int i = 0; i < width; i++) {
+ if (val_arst[i] == State::S1)
+ sig_set[i] = sig_arst;
+ else
+ sig_clr[i] = sig_arst;
+ }
+}
+
+void FfData::aload_to_sr() {
+ log_assert(has_aload);
+ log_assert(!has_sr);
+ has_sr = true;
+ has_aload = false;
+ if (!is_fine) {
+ pol_clr = false;
+ pol_set = true;
+ if (pol_aload) {
+ sig_clr = module->Mux(NEW_ID, Const(State::S1, width), sig_ad, sig_aload);
+ sig_set = module->Mux(NEW_ID, Const(State::S0, width), sig_ad, sig_aload);
+ } else {
+ sig_clr = module->Mux(NEW_ID, sig_ad, Const(State::S1, width), sig_aload);
+ sig_set = module->Mux(NEW_ID, sig_ad, Const(State::S0, width), sig_aload);
+ }
+ } else {
+ pol_clr = pol_aload;
+ pol_set = pol_aload;
+ if (pol_aload) {
+ sig_clr = module->AndnotGate(NEW_ID, sig_aload, sig_ad);
+ sig_set = module->AndGate(NEW_ID, sig_aload, sig_ad);
+ } else {
+ sig_clr = module->OrGate(NEW_ID, sig_aload, sig_ad);
+ sig_set = module->OrnotGate(NEW_ID, sig_aload, sig_ad);
+ }
+ }
+}
+
+void FfData::convert_ce_over_srst(bool val) {
+ if (!has_ce || !has_srst || ce_over_srst == val)
+ return;
+ if (val) {
+ // sdffe to sdffce
+ if (!is_fine) {
+ if (pol_ce) {
+ if (pol_srst) {
+ sig_ce = module->Or(NEW_ID, sig_ce, sig_srst);
+ } else {
+ SigSpec tmp = module->Not(NEW_ID, sig_srst);
+ sig_ce = module->Or(NEW_ID, sig_ce, tmp);
+ }
+ } else {
+ if (pol_srst) {
+ SigSpec tmp = module->Not(NEW_ID, sig_srst);
+ sig_ce = module->And(NEW_ID, sig_ce, tmp);
+ } else {
+ sig_ce = module->And(NEW_ID, sig_ce, sig_srst);
+ }
+ }
+ } else {
+ if (pol_ce) {
+ if (pol_srst) {
+ sig_ce = module->OrGate(NEW_ID, sig_ce, sig_srst);
+ } else {
+ sig_ce = module->OrnotGate(NEW_ID, sig_ce, sig_srst);
+ }
+ } else {
+ if (pol_srst) {
+ sig_ce = module->AndnotGate(NEW_ID, sig_ce, sig_srst);
+ } else {
+ sig_ce = module->AndGate(NEW_ID, sig_ce, sig_srst);
+ }
+ }
+ }
+ } else {
+ // sdffce to sdffe
+ if (!is_fine) {
+ if (pol_srst) {
+ if (pol_ce) {
+ sig_srst = cell->module->And(NEW_ID, sig_srst, sig_ce);
+ } else {
+ SigSpec tmp = module->Not(NEW_ID, sig_ce);
+ sig_srst = cell->module->And(NEW_ID, sig_srst, tmp);
+ }
+ } else {
+ if (pol_ce) {
+ SigSpec tmp = module->Not(NEW_ID, sig_ce);
+ sig_srst = cell->module->Or(NEW_ID, sig_srst, tmp);
+ } else {
+ sig_srst = cell->module->Or(NEW_ID, sig_srst, sig_ce);
+ }
+ }
+ } else {
+ if (pol_srst) {
+ if (pol_ce) {
+ sig_srst = cell->module->AndGate(NEW_ID, sig_srst, sig_ce);
+ } else {
+ sig_srst = cell->module->AndnotGate(NEW_ID, sig_srst, sig_ce);
+ }
+ } else {
+ if (pol_ce) {
+ sig_srst = cell->module->OrnotGate(NEW_ID, sig_srst, sig_ce);
+ } else {
+ sig_srst = cell->module->OrGate(NEW_ID, sig_srst, sig_ce);
+ }
+ }
+ }
+ }
+ ce_over_srst = val;
+}
+
+void FfData::unmap_ce() {
+ if (!has_ce)
+ return;
+ log_assert(has_clk);
+ if (has_srst && ce_over_srst)
+ unmap_srst();
+
+ if (!is_fine) {
+ if (pol_ce)
+ sig_d = module->Mux(NEW_ID, sig_q, sig_d, sig_ce);
+ else
+ sig_d = module->Mux(NEW_ID, sig_d, sig_q, sig_ce);
+ } else {
+ if (pol_ce)
+ sig_d = module->MuxGate(NEW_ID, sig_q, sig_d, sig_ce);
+ else
+ sig_d = module->MuxGate(NEW_ID, sig_d, sig_q, sig_ce);
+ }
+ has_ce = false;
+}
+
+void FfData::unmap_srst() {
+ if (!has_srst)
+ return;
+ if (has_ce && !ce_over_srst)
+ unmap_ce();
+
+ if (!is_fine) {
+ if (pol_srst)
+ sig_d = module->Mux(NEW_ID, sig_d, val_srst, sig_srst);
+ else
+ sig_d = module->Mux(NEW_ID, val_srst, sig_d, sig_srst);
+ } else {
+ if (pol_srst)
+ sig_d = module->MuxGate(NEW_ID, sig_d, val_srst[0], sig_srst);
+ else
+ sig_d = module->MuxGate(NEW_ID, val_srst[0], sig_d, sig_srst);
+ }
+ has_srst = false;
+}
+
+Cell *FfData::emit() {
+ remove();
+ if (!width)
+ return nullptr;
+ if (!has_aload && !has_clk && !has_gclk && !has_sr) {
+ if (has_arst) {
+ // Convert this case to a D latch.
+ arst_to_aload();
+ } else {
+ // No control inputs left. Turn into a const driver.
+ module->connect(sig_q, val_init);
+ return nullptr;
+ }
+ }
+ if (initvals)
+ initvals->set_init(sig_q, val_init);
+ if (!is_fine) {
+ if (has_gclk) {
+ log_assert(!has_clk);
+ log_assert(!has_ce);
+ log_assert(!has_aload);
+ log_assert(!has_arst);
+ log_assert(!has_srst);
+ log_assert(!has_sr);
+ cell = module->addFf(name, sig_d, sig_q);
+ } else if (!has_aload && !has_clk) {
+ log_assert(has_sr);
+ cell = module->addSr(name, sig_set, sig_clr, sig_q, pol_set, pol_clr);
+ } else if (!has_clk) {
+ log_assert(!has_srst);
+ if (has_sr)
+ cell = module->addDlatchsr(name, sig_aload, sig_set, sig_clr, sig_ad, sig_q, pol_aload, pol_set, pol_clr);
+ else if (has_arst)
+ cell = module->addAdlatch(name, sig_aload, sig_arst, sig_ad, sig_q, val_arst, pol_aload, pol_arst);
+ else
+ cell = module->addDlatch(name, sig_aload, sig_ad, sig_q, pol_aload);
+ } else {
+ if (has_sr) {
+ if (has_ce)
+ cell = module->addDffsre(name, sig_clk, sig_ce, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_ce, pol_set, pol_clr);
+ else
+ cell = module->addDffsr(name, sig_clk, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_set, pol_clr);
+ } else if (has_arst) {
+ if (has_ce)
+ cell = module->addAdffe(name, sig_clk, sig_ce, sig_arst, sig_d, sig_q, val_arst, pol_clk, pol_ce, pol_arst);
+ else
+ cell = module->addAdff(name, sig_clk, sig_arst, sig_d, sig_q, val_arst, pol_clk, pol_arst);
+ } else if (has_aload) {
+ if (has_ce)
+ cell = module->addAldffe(name, sig_clk, sig_ce, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_ce, pol_aload);
+ else
+ cell = module->addAldff(name, sig_clk, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_aload);
+ } else if (has_srst) {
+ if (has_ce)
+ if (ce_over_srst)
+ cell = module->addSdffce(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_ce, pol_srst);
+ else
+ cell = module->addSdffe(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_ce, pol_srst);
+ else
+ cell = module->addSdff(name, sig_clk, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_srst);
+ } else {
+ if (has_ce)
+ cell = module->addDffe(name, sig_clk, sig_ce, sig_d, sig_q, pol_clk, pol_ce);
+ else
+ cell = module->addDff(name, sig_clk, sig_d, sig_q, pol_clk);
+ }
+ }
+ } else {
+ if (has_gclk) {
+ log_assert(!has_clk);
+ log_assert(!has_ce);
+ log_assert(!has_aload);
+ log_assert(!has_arst);
+ log_assert(!has_srst);
+ log_assert(!has_sr);
+ cell = module->addFfGate(name, sig_d, sig_q);
+ } else if (!has_aload && !has_clk) {
+ log_assert(has_sr);
+ cell = module->addSrGate(name, sig_set, sig_clr, sig_q, pol_set, pol_clr);
+ } else if (!has_clk) {
+ log_assert(!has_srst);
+ if (has_sr)
+ cell = module->addDlatchsrGate(name, sig_aload, sig_set, sig_clr, sig_ad, sig_q, pol_aload, pol_set, pol_clr);
+ else if (has_arst)
+ cell = module->addAdlatchGate(name, sig_aload, sig_arst, sig_ad, sig_q, val_arst.as_bool(), pol_aload, pol_arst);
+ else
+ cell = module->addDlatchGate(name, sig_aload, sig_ad, sig_q, pol_aload);
+ } else {
+ if (has_sr) {
+ if (has_ce)
+ cell = module->addDffsreGate(name, sig_clk, sig_ce, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_ce, pol_set, pol_clr);
+ else
+ cell = module->addDffsrGate(name, sig_clk, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_set, pol_clr);
+ } else if (has_arst) {
+ if (has_ce)
+ cell = module->addAdffeGate(name, sig_clk, sig_ce, sig_arst, sig_d, sig_q, val_arst.as_bool(), pol_clk, pol_ce, pol_arst);
+ else
+ cell = module->addAdffGate(name, sig_clk, sig_arst, sig_d, sig_q, val_arst.as_bool(), pol_clk, pol_arst);
+ } else if (has_aload) {
+ if (has_ce)
+ cell = module->addAldffeGate(name, sig_clk, sig_ce, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_ce, pol_aload);
+ else
+ cell = module->addAldffGate(name, sig_clk, sig_aload, sig_d, sig_q, sig_ad, pol_clk, pol_aload);
+ } else if (has_srst) {
+ if (has_ce)
+ if (ce_over_srst)
+ cell = module->addSdffceGate(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_ce, pol_srst);
+ else
+ cell = module->addSdffeGate(name, sig_clk, sig_ce, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_ce, pol_srst);
+ else
+ cell = module->addSdffGate(name, sig_clk, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_srst);
+ } else {
+ if (has_ce)
+ cell = module->addDffeGate(name, sig_clk, sig_ce, sig_d, sig_q, pol_clk, pol_ce);
+ else
+ cell = module->addDffGate(name, sig_clk, sig_d, sig_q, pol_clk);
+ }
+ }
+ }
+ cell->attributes = attributes;
+ return cell;
+}
+
+void FfData::remove() {
+ if (cell) {
+ remove_init();
+ module->remove(cell);
+ cell = nullptr;
+ }
+}
+
+namespace {
+ State invert(State s) {
+ switch (s) {
+ case State::S0: return State::S1;
+ case State::S1: return State::S0;
+ default: return s;
+ }
+ }
+}
+
+void FfData::flip_bits(const pool<int> &bits) {
+ if (!bits.size())
+ return;
+
+ remove_init();
+
+ Wire *new_q = module->addWire(NEW_ID, width);
+
+ for (auto bit: bits) {
+ if (has_arst)
+ val_arst[bit] = invert(val_arst[bit]);
+ if (has_srst)
+ val_srst[bit] = invert(val_srst[bit]);
+ val_init[bit] = invert(val_init[bit]);
+ }
+
+ if (has_sr && cell) {
+ log_warning("Flipping D/Q/init and inserting priority fixup to legalize %s.%s [%s].\n", log_id(module->name), log_id(cell->name), log_id(cell->type));
+ }
+
+ if (is_fine) {
+ if (has_sr) {
+ bool new_pol_clr = pol_set;
+ SigSpec new_sig_clr;
+ if (pol_set) {
+ if (pol_clr) {
+ new_sig_clr = module->AndnotGate(NEW_ID, sig_set, sig_clr);
+ } else {
+ new_sig_clr = module->AndGate(NEW_ID, sig_set, sig_clr);
+ }
+ } else {
+ if (pol_clr) {
+ new_sig_clr = module->OrGate(NEW_ID, sig_set, sig_clr);
+ } else {
+ new_sig_clr = module->OrnotGate(NEW_ID, sig_set, sig_clr);
+ }
+ }
+ pol_set = pol_clr;
+ sig_set = sig_clr;
+ pol_clr = new_pol_clr;
+ sig_clr = new_sig_clr;
+ }
+ if (has_clk || has_gclk)
+ sig_d = module->NotGate(NEW_ID, sig_d);
+ if (has_aload)
+ sig_ad = module->NotGate(NEW_ID, sig_ad);
+ module->addNotGate(NEW_ID, new_q, sig_q);
+ }
+ else
+ {
+ if (has_sr) {
+ SigSpec not_clr;
+ if (!pol_clr) {
+ not_clr = sig_clr;
+ sig_clr = module->Not(NEW_ID, sig_clr);
+ pol_clr = true;
+ } else {
+ not_clr = module->Not(NEW_ID, sig_clr);
+ }
+ if (!pol_set) {
+ sig_set = module->Not(NEW_ID, sig_set);
+ pol_set = true;
+ }
+
+ SigSpec masked_set = module->And(NEW_ID, sig_set, not_clr);
+ for (auto bit: bits) {
+ sig_set[bit] = sig_clr[bit];
+ sig_clr[bit] = masked_set[bit];
+ }
+ }
+
+ Const mask = Const(State::S0, width);
+ for (auto bit: bits)
+ mask.bits[bit] = State::S1;
+
+ if (has_clk || has_gclk)
+ sig_d = module->Xor(NEW_ID, sig_d, mask);
+ if (has_aload)
+ sig_ad = module->Xor(NEW_ID, sig_ad, mask);
+ module->addXor(NEW_ID, new_q, mask, sig_q);
+ }
+
+ sig_q = new_q;
+}
diff --git a/kernel/ff.h b/kernel/ff.h
index 0aecbaa2a..5a629d5dd 100644
--- a/kernel/ff.h
+++ b/kernel/ff.h
@@ -25,460 +25,190 @@
YOSYS_NAMESPACE_BEGIN
+// Describes a flip-flop or a latch.
+//
+// If has_gclk, this is a formal verification FF with implicit global clock:
+// Q is simply previous cycle's D.
+//
+// Otherwise, the FF/latch can have any number of features selected by has_*
+// attributes that determine Q's value (in order of decreasing priority):
+//
+// - on start, register is initialized to val_init
+// - if has_sr is present:
+// - sig_clr is per-bit async clear, and sets the corresponding bit to 0
+// if active
+// - sig_set is per-bit async set, and sets the corresponding bit to 1
+// if active
+// - if has_arst is present:
+// - sig_arst is whole-reg async reset, and sets the whole register to val_arst
+// - if has_aload is present:
+// - sig_aload is whole-reg async load (aka latch gate enable), and sets the whole
+// register to sig_ad
+// - if has_clk is present, and we're currently on a clock edge:
+// - if has_ce is present and ce_over_srst is true:
+// - ignore clock edge (don't change value) unless sig_ce is active
+// - if has_srst is present:
+// - sig_srst is whole-reg sync reset and sets the register to val_srst
+// - if has_ce is present and ce_over_srst is false:
+// - ignore clock edge (don't change value) unless sig_ce is active
+// - set whole reg to sig_d
+// - if nothing of the above applies, the reg value remains unchanged
+//
+// Since the yosys FF cell library isn't fully generic, not all combinations
+// of the features above can be supported:
+//
+// - only one of has_srst, has_arst, has_sr can be used
+// - if has_clk is used together with has_aload, then has_srst, has_arst,
+// has_sr cannot be used
+//
+// The valid feature combinations are thus:
+//
+// - has_clk + optional has_ce [dff/dffe]
+// - has_clk + optional has_ce + has_arst [adff/adffe]
+// - has_clk + optional has_ce + has_aload [aldff/aldffe]
+// - has_clk + optional has_ce + has_sr [dffsr/dffsre]
+// - has_clk + optional has_ce + has_srst [sdff/sdffe/sdffce]
+// - has_aload [dlatch]
+// - has_aload + has_arst [adlatch]
+// - has_aload + has_sr [dlatchsr]
+// - has_sr [sr]
+// - has_arst [does not correspond to a native cell, represented as dlatch with const D input]
+// - empty set [not a cell — will be emitted as a simple direct connection]
+
struct FfData {
+ Module *module;
FfInitVals *initvals;
+ Cell *cell;
+ IdString name;
+ // The FF output.
SigSpec sig_q;
+ // The sync data input, present if has_clk or has_gclk.
SigSpec sig_d;
+ // The async data input, present if has_aload.
+ SigSpec sig_ad;
+ // The sync clock, present if has_clk.
SigSpec sig_clk;
- SigSpec sig_en;
+ // The clock enable, present if has_ce.
+ SigSpec sig_ce;
+ // The async load enable, present if has_aload.
+ SigSpec sig_aload;
+ // The async reset, preset if has_arst.
SigSpec sig_arst;
+ // The sync reset, preset if has_srst.
SigSpec sig_srst;
+ // The async clear (per-lane), present if has_sr.
SigSpec sig_clr;
+ // The async set (per-lane), present if has_sr.
SigSpec sig_set;
- bool has_d;
+ // True if this is a clocked (edge-sensitive) flip-flop.
bool has_clk;
- bool has_en;
+ // True if this is a $ff, exclusive with every other has_*.
+ bool has_gclk;
+ // True if this FF has a clock enable. Depends on has_clk.
+ bool has_ce;
+ // True if this FF has async load function — this includes D latches.
+ // If this and has_clk are both set, has_arst and has_sr cannot be set.
+ bool has_aload;
+ // True if this FF has sync set/reset. Depends on has_clk, exclusive
+ // with has_arst, has_sr, has_aload.
bool has_srst;
+ // True if this FF has async set/reset. Exclusive with has_srst,
+ // has_sr. If this and has_clk are both set, has_aload cannot be set.
bool has_arst;
+ // True if this FF has per-bit async set + clear. Exclusive with
+ // has_srst, has_arst. If this and has_clk are both set, has_aload
+ // cannot be set.
bool has_sr;
+ // If has_ce and has_srst are both set, determines their relative
+ // priorities: if true, inactive ce disables srst; if false, srst
+ // operates independent of ce.
bool ce_over_srst;
+ // True if this FF is a fine cell, false if it is a coarse cell.
+ // If true, width must be 1.
bool is_fine;
+ // Polarities, corresponding to sig_*. True means active-high, false
+ // means active-low.
bool pol_clk;
- bool pol_en;
+ bool pol_ce;
+ bool pol_aload;
bool pol_arst;
bool pol_srst;
bool pol_clr;
bool pol_set;
+ // The value loaded by sig_arst.
Const val_arst;
+ // The value loaded by sig_srst.
Const val_srst;
+ // The initial value at power-up.
Const val_init;
- Const val_d;
- bool d_is_const;
+ // The FF data width in bits.
int width;
dict<IdString, Const> attributes;
- FfData(FfInitVals *initvals, Cell *cell = nullptr) : initvals(initvals) {
+ FfData(Module *module = nullptr, FfInitVals *initvals = nullptr, IdString name = IdString()) : module(module), initvals(initvals), cell(nullptr), name(name) {
width = 0;
- has_d = true;
has_clk = false;
- has_en = false;
+ has_gclk = false;
+ has_ce = false;
+ has_aload = false;
has_srst = false;
has_arst = false;
has_sr = false;
ce_over_srst = false;
is_fine = false;
pol_clk = false;
- pol_en = false;
+ pol_aload = false;
+ pol_ce = false;
pol_arst = false;
pol_srst = false;
pol_clr = false;
pol_set = false;
- d_is_const = false;
+ }
- if (!cell)
- return;
+ FfData(FfInitVals *initvals, Cell *cell_);
- sig_q = cell->getPort(ID::Q);
- width = GetSize(sig_q);
- attributes = cell->attributes;
+ // Returns a FF identical to this one, but only keeping bit indices from the argument.
+ FfData slice(const std::vector<int> &bits);
- if (initvals)
- val_init = (*initvals)(sig_q);
+ void add_dummy_ce();
+ void add_dummy_srst();
+ void add_dummy_arst();
+ void add_dummy_aload();
+ void add_dummy_sr();
+ void add_dummy_clk();
- std::string type_str = cell->type.str();
+ void arst_to_aload();
+ void arst_to_sr();
- if (cell->type.in(ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch), ID($dlatchsr), ID($sr))) {
- if (cell->type == ID($sr)) {
- has_d = false;
- } else {
- sig_d = cell->getPort(ID::D);
- }
- if (!cell->type.in(ID($ff), ID($dlatch), ID($adlatch), ID($dlatchsr), ID($sr))) {
- has_clk = true;
- sig_clk = cell->getPort(ID::CLK);
- pol_clk = cell->getParam(ID::CLK_POLARITY).as_bool();
- }
- if (cell->type.in(ID($dffe), ID($dffsre), ID($adffe), ID($sdffe), ID($sdffce), ID($dlatch), ID($adlatch), ID($dlatchsr))) {
- has_en = true;
- sig_en = cell->getPort(ID::EN);
- pol_en = cell->getParam(ID::EN_POLARITY).as_bool();
- }
- if (cell->type.in(ID($dffsr), ID($dffsre), ID($dlatchsr), ID($sr))) {
- has_sr = true;
- sig_clr = cell->getPort(ID::CLR);
- sig_set = cell->getPort(ID::SET);
- pol_clr = cell->getParam(ID::CLR_POLARITY).as_bool();
- pol_set = cell->getParam(ID::SET_POLARITY).as_bool();
- }
- if (cell->type.in(ID($adff), ID($adffe), ID($adlatch))) {
- has_arst = true;
- sig_arst = cell->getPort(ID::ARST);
- pol_arst = cell->getParam(ID::ARST_POLARITY).as_bool();
- val_arst = cell->getParam(ID::ARST_VALUE);
- }
- if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce))) {
- has_srst = true;
- sig_srst = cell->getPort(ID::SRST);
- pol_srst = cell->getParam(ID::SRST_POLARITY).as_bool();
- val_srst = cell->getParam(ID::SRST_VALUE);
- ce_over_srst = cell->type == ID($sdffce);
- }
- } else if (cell->type == ID($_FF_)) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- } else if (type_str.substr(0, 5) == "$_SR_") {
- is_fine = true;
- has_d = false;
- has_sr = true;
- pol_set = type_str[5] == 'P';
- pol_clr = type_str[6] == 'P';
- sig_set = cell->getPort(ID::S);
- sig_clr = cell->getPort(ID::R);
- } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 8) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[6] == 'P';
- sig_clk = cell->getPort(ID::C);
- } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 10) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[7] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_en = true;
- pol_en = type_str[8] == 'P';
- sig_en = cell->getPort(ID::E);
- } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 10) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[6] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_arst = true;
- pol_arst = type_str[7] == 'P';
- sig_arst = cell->getPort(ID::R);
- val_arst = type_str[8] == '1' ? State::S1 : State::S0;
- } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 12) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[7] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_arst = true;
- pol_arst = type_str[8] == 'P';
- sig_arst = cell->getPort(ID::R);
- val_arst = type_str[9] == '1' ? State::S1 : State::S0;
- has_en = true;
- pol_en = type_str[10] == 'P';
- sig_en = cell->getPort(ID::E);
- } else if (type_str.substr(0, 8) == "$_DFFSR_" && type_str.size() == 12) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[8] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_sr = true;
- pol_set = type_str[9] == 'P';
- pol_clr = type_str[10] == 'P';
- sig_set = cell->getPort(ID::S);
- sig_clr = cell->getPort(ID::R);
- } else if (type_str.substr(0, 9) == "$_DFFSRE_" && type_str.size() == 14) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[9] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_sr = true;
- pol_set = type_str[10] == 'P';
- pol_clr = type_str[11] == 'P';
- sig_set = cell->getPort(ID::S);
- sig_clr = cell->getPort(ID::R);
- has_en = true;
- pol_en = type_str[12] == 'P';
- sig_en = cell->getPort(ID::E);
- } else if (type_str.substr(0, 7) == "$_SDFF_" && type_str.size() == 11) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[7] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_srst = true;
- pol_srst = type_str[8] == 'P';
- sig_srst = cell->getPort(ID::R);
- val_srst = type_str[9] == '1' ? State::S1 : State::S0;
- } else if (type_str.substr(0, 8) == "$_SDFFE_" && type_str.size() == 13) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[8] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_srst = true;
- pol_srst = type_str[9] == 'P';
- sig_srst = cell->getPort(ID::R);
- val_srst = type_str[10] == '1' ? State::S1 : State::S0;
- has_en = true;
- pol_en = type_str[11] == 'P';
- sig_en = cell->getPort(ID::E);
- } else if (type_str.substr(0, 9) == "$_SDFFCE_" && type_str.size() == 14) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_clk = true;
- pol_clk = type_str[9] == 'P';
- sig_clk = cell->getPort(ID::C);
- has_srst = true;
- pol_srst = type_str[10] == 'P';
- sig_srst = cell->getPort(ID::R);
- val_srst = type_str[11] == '1' ? State::S1 : State::S0;
- has_en = true;
- pol_en = type_str[12] == 'P';
- sig_en = cell->getPort(ID::E);
- ce_over_srst = true;
- } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 11) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_en = true;
- pol_en = type_str[9] == 'P';
- sig_en = cell->getPort(ID::E);
- } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 13) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_en = true;
- pol_en = type_str[9] == 'P';
- sig_en = cell->getPort(ID::E);
- has_arst = true;
- pol_arst = type_str[10] == 'P';
- sig_arst = cell->getPort(ID::R);
- val_arst = type_str[11] == '1' ? State::S1 : State::S0;
- } else if (type_str.substr(0, 11) == "$_DLATCHSR_" && type_str.size() == 15) {
- is_fine = true;
- sig_d = cell->getPort(ID::D);
- has_en = true;
- pol_en = type_str[11] == 'P';
- sig_en = cell->getPort(ID::E);
- has_sr = true;
- pol_set = type_str[12] == 'P';
- pol_clr = type_str[13] == 'P';
- sig_set = cell->getPort(ID::S);
- sig_clr = cell->getPort(ID::R);
- } else {
- log_assert(0);
- }
- if (has_d && sig_d.is_fully_const()) {
- d_is_const = true;
- val_d = sig_d.as_const();
- if (has_en && !has_clk && !has_sr && !has_arst) {
- // Plain D latches with const D treated specially.
- has_en = has_d = false;
- has_arst = true;
- sig_arst = sig_en;
- pol_arst = pol_en;
- val_arst = val_d;
- }
- }
- }
+ void aload_to_sr();
- // Returns a FF identical to this one, but only keeping bit indices from the argument.
- FfData slice(const std::vector<int> &bits) {
- FfData res(initvals);
- res.sig_clk = sig_clk;
- res.sig_en = sig_en;
- res.sig_arst = sig_arst;
- res.sig_srst = sig_srst;
- res.has_d = has_d;
- res.has_clk = has_clk;
- res.has_en = has_en;
- res.has_arst = has_arst;
- res.has_srst = has_srst;
- res.has_sr = has_sr;
- res.ce_over_srst = ce_over_srst;
- res.is_fine = is_fine;
- res.pol_clk = pol_clk;
- res.pol_en = pol_en;
- res.pol_arst = pol_arst;
- res.pol_srst = pol_srst;
- res.pol_clr = pol_clr;
- res.pol_set = pol_set;
- res.attributes = attributes;
- for (int i : bits) {
- res.sig_q.append(sig_q[i]);
- if (has_d)
- res.sig_d.append(sig_d[i]);
- if (has_sr) {
- res.sig_clr.append(sig_clr[i]);
- res.sig_set.append(sig_set[i]);
- }
- if (has_arst)
- res.val_arst.bits.push_back(val_arst[i]);
- if (has_srst)
- res.val_srst.bits.push_back(val_srst[i]);
- res.val_init.bits.push_back(val_init[i]);
- }
- res.width = GetSize(res.sig_q);
- // Slicing bits out may cause D to become const.
- if (has_d && res.sig_d.is_fully_const()) {
- res.d_is_const = true;
- res.val_d = res.sig_d.as_const();
- }
- return res;
- }
+ // Given a FF with both has_ce and has_srst, sets ce_over_srst to the given value and
+ // fixes up control signals appropriately to preserve semantics.
+ void convert_ce_over_srst(bool val);
- void unmap_ce(Module *module) {
- if (!has_en)
- return;
- log_assert(has_clk);
- if (has_srst && ce_over_srst)
- unmap_srst(module);
+ void unmap_ce();
+ void unmap_srst();
- if (!is_fine) {
- if (pol_en)
- sig_d = module->Mux(NEW_ID, sig_q, sig_d, sig_en);
- else
- sig_d = module->Mux(NEW_ID, sig_d, sig_q, sig_en);
- } else {
- if (pol_en)
- sig_d = module->MuxGate(NEW_ID, sig_q, sig_d, sig_en);
- else
- sig_d = module->MuxGate(NEW_ID, sig_d, sig_q, sig_en);
- }
- has_en = false;
+ void unmap_ce_srst() {
+ unmap_ce();
+ unmap_srst();
}
- void unmap_srst(Module *module) {
- if (!has_srst)
- return;
- if (has_en && !ce_over_srst)
- unmap_ce(module);
+ Cell *emit();
- if (!is_fine) {
- if (pol_srst)
- sig_d = module->Mux(NEW_ID, sig_d, val_srst, sig_srst);
- else
- sig_d = module->Mux(NEW_ID, val_srst, sig_d, sig_srst);
- } else {
- if (pol_srst)
- sig_d = module->MuxGate(NEW_ID, sig_d, val_srst[0], sig_srst);
- else
- sig_d = module->MuxGate(NEW_ID, val_srst[0], sig_d, sig_srst);
- }
- has_srst = false;
+ // Removes init attribute from the Q output, but keeps val_init unchanged.
+ // It will be automatically reattached on emit. Use this before changing sig_q.
+ void remove_init() {
+ if (initvals)
+ initvals->remove_init(sig_q);
}
- void unmap_ce_srst(Module *module) {
- unmap_ce(module);
- unmap_srst(module);
- }
+ void remove();
- Cell *emit(Module *module, IdString name) {
- if (!width)
- return nullptr;
- if (!has_d && !has_sr) {
- if (has_arst) {
- // Convert this case to a D latch.
- has_d = has_en = true;
- has_arst = false;
- sig_d = val_arst;
- sig_en = sig_arst;
- pol_en = pol_arst;
- } else {
- // No control inputs left. Turn into a const driver.
- initvals->remove_init(sig_q);
- module->connect(sig_q, val_init);
- return nullptr;
- }
- }
- initvals->set_init(sig_q, val_init);
- Cell *cell;
- if (!is_fine) {
- if (!has_d) {
- log_assert(has_sr);
- cell = module->addSr(name, sig_set, sig_clr, sig_q, pol_set, pol_clr);
- } else if (!has_clk && !has_en) {
- log_assert(!has_arst);
- log_assert(!has_srst);
- log_assert(!has_sr);
- cell = module->addFf(name, sig_d, sig_q);
- } else if (!has_clk) {
- log_assert(!has_srst);
- if (has_sr)
- cell = module->addDlatchsr(name, sig_en, sig_set, sig_clr, sig_d, sig_q, pol_en, pol_set, pol_clr);
- else if (has_arst)
- cell = module->addAdlatch(name, sig_en, sig_arst, sig_d, sig_q, val_arst, pol_en, pol_arst);
- else
- cell = module->addDlatch(name, sig_en, sig_d, sig_q, pol_en);
- } else {
- if (has_sr) {
- if (has_en)
- cell = module->addDffsre(name, sig_clk, sig_en, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_en, pol_set, pol_clr);
- else
- cell = module->addDffsr(name, sig_clk, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_set, pol_clr);
- } else if (has_arst) {
- if (has_en)
- cell = module->addAdffe(name, sig_clk, sig_en, sig_arst, sig_d, sig_q, val_arst, pol_clk, pol_en, pol_arst);
- else
- cell = module->addAdff(name, sig_clk, sig_arst, sig_d, sig_q, val_arst, pol_clk, pol_arst);
- } else if (has_srst) {
- if (has_en)
- if (ce_over_srst)
- cell = module->addSdffce(name, sig_clk, sig_en, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_en, pol_srst);
- else
- cell = module->addSdffe(name, sig_clk, sig_en, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_en, pol_srst);
- else
- cell = module->addSdff(name, sig_clk, sig_srst, sig_d, sig_q, val_srst, pol_clk, pol_srst);
- } else {
- if (has_en)
- cell = module->addDffe(name, sig_clk, sig_en, sig_d, sig_q, pol_clk, pol_en);
- else
- cell = module->addDff(name, sig_clk, sig_d, sig_q, pol_clk);
- }
- }
- } else {
- if (!has_d) {
- log_assert(has_sr);
- cell = module->addSrGate(name, sig_set, sig_clr, sig_q, pol_set, pol_clr);
- } else if (!has_clk && !has_en) {
- log_assert(!has_arst);
- log_assert(!has_srst);
- log_assert(!has_sr);
- cell = module->addFfGate(name, sig_d, sig_q);
- } else if (!has_clk) {
- log_assert(!has_srst);
- if (has_sr)
- cell = module->addDlatchsrGate(name, sig_en, sig_set, sig_clr, sig_d, sig_q, pol_en, pol_set, pol_clr);
- else if (has_arst)
- cell = module->addAdlatchGate(name, sig_en, sig_arst, sig_d, sig_q, val_arst.as_bool(), pol_en, pol_arst);
- else
- cell = module->addDlatchGate(name, sig_en, sig_d, sig_q, pol_en);
- } else {
- if (has_sr) {
- if (has_en)
- cell = module->addDffsreGate(name, sig_clk, sig_en, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_en, pol_set, pol_clr);
- else
- cell = module->addDffsrGate(name, sig_clk, sig_set, sig_clr, sig_d, sig_q, pol_clk, pol_set, pol_clr);
- } else if (has_arst) {
- if (has_en)
- cell = module->addAdffeGate(name, sig_clk, sig_en, sig_arst, sig_d, sig_q, val_arst.as_bool(), pol_clk, pol_en, pol_arst);
- else
- cell = module->addAdffGate(name, sig_clk, sig_arst, sig_d, sig_q, val_arst.as_bool(), pol_clk, pol_arst);
- } else if (has_srst) {
- if (has_en)
- if (ce_over_srst)
- cell = module->addSdffceGate(name, sig_clk, sig_en, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_en, pol_srst);
- else
- cell = module->addSdffeGate(name, sig_clk, sig_en, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_en, pol_srst);
- else
- cell = module->addSdffGate(name, sig_clk, sig_srst, sig_d, sig_q, val_srst.as_bool(), pol_clk, pol_srst);
- } else {
- if (has_en)
- cell = module->addDffeGate(name, sig_clk, sig_en, sig_d, sig_q, pol_clk, pol_en);
- else
- cell = module->addDffGate(name, sig_clk, sig_d, sig_q, pol_clk);
- }
- }
- }
- cell->attributes = attributes;
- return cell;
- }
+ // Flip the sense of the given bit slices of the FF: insert inverters on data
+ // inputs and output, flip the corresponding init/reset bits, swap clr/set
+ // inputs with proper priority fix.
+ void flip_bits(const pool<int> &bits);
};
YOSYS_NAMESPACE_END
diff --git a/kernel/ffinit.h b/kernel/ffinit.h
index 025b0c862..9d33ac572 100644
--- a/kernel/ffinit.h
+++ b/kernel/ffinit.h
@@ -28,7 +28,6 @@ YOSYS_NAMESPACE_BEGIN
struct FfInitVals
{
const SigMap *sigmap;
- RTLIL::Module *module;
dict<SigBit, std::pair<State,SigBit>> initbits;
void set(const SigMap *sigmap_, RTLIL::Module *module)
diff --git a/kernel/ffmerge.cc b/kernel/ffmerge.cc
new file mode 100644
index 000000000..c65108413
--- /dev/null
+++ b/kernel/ffmerge.cc
@@ -0,0 +1,359 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * 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/ffmerge.h"
+
+USING_YOSYS_NAMESPACE
+
+bool FfMergeHelper::is_output_unused(RTLIL::SigSpec sig) {
+ for (auto bit : (*sigmap)(sig))
+ if (sigbit_users_count[bit] != 0)
+ return false;
+ return true;
+}
+
+bool FfMergeHelper::find_output_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pair<Cell *, int>> &bits) {
+ ff = FfData(module, initvals, NEW_ID);
+ sigmap->apply(sig);
+
+ bool found = false;
+
+ for (auto bit : sig)
+ {
+ if (bit.wire == NULL || sigbit_users_count[bit] == 0) {
+ ff.width++;
+ ff.sig_q.append(bit);
+ ff.sig_d.append(bit);
+ ff.sig_clr.append(State::Sx);
+ ff.sig_set.append(State::Sx);
+ ff.val_init.bits.push_back(State::Sx);
+ ff.val_srst.bits.push_back(State::Sx);
+ ff.val_arst.bits.push_back(State::Sx);
+ continue;
+ }
+
+ if (sigbit_users_count[bit] != 1)
+ return false;
+
+ auto &sinks = dff_sink[bit];
+ if (sinks.size() != 1)
+ return false;
+
+ Cell *cell;
+ int idx;
+ std::tie(cell, idx) = *sinks.begin();
+ bits.insert(std::make_pair(cell, idx));
+
+ FfData cur_ff(initvals, cell);
+
+ // Reject latches and $ff.
+ if (!cur_ff.has_clk)
+ return false;
+
+ log_assert((*sigmap)(cur_ff.sig_d[idx]) == bit);
+
+ if (!found) {
+ ff.sig_clk = cur_ff.sig_clk;
+ ff.sig_ce = cur_ff.sig_ce;
+ ff.sig_aload = cur_ff.sig_aload;
+ ff.sig_srst = cur_ff.sig_srst;
+ ff.sig_arst = cur_ff.sig_arst;
+ ff.has_clk = cur_ff.has_clk;
+ ff.has_ce = cur_ff.has_ce;
+ ff.has_aload = cur_ff.has_aload;
+ ff.has_srst = cur_ff.has_srst;
+ ff.has_arst = cur_ff.has_arst;
+ ff.has_sr = cur_ff.has_sr;
+ ff.ce_over_srst = cur_ff.ce_over_srst;
+ ff.pol_clk = cur_ff.pol_clk;
+ ff.pol_ce = cur_ff.pol_ce;
+ ff.pol_aload = cur_ff.pol_aload;
+ ff.pol_arst = cur_ff.pol_arst;
+ ff.pol_srst = cur_ff.pol_srst;
+ ff.pol_clr = cur_ff.pol_clr;
+ ff.pol_set = cur_ff.pol_set;
+ } else {
+ if (ff.has_clk != cur_ff.has_clk)
+ return false;
+ if (ff.has_ce != cur_ff.has_ce)
+ return false;
+ if (ff.has_aload != cur_ff.has_aload)
+ return false;
+ if (ff.has_srst != cur_ff.has_srst)
+ return false;
+ if (ff.has_arst != cur_ff.has_arst)
+ return false;
+ if (ff.has_sr != cur_ff.has_sr)
+ return false;
+ if (ff.has_clk) {
+ if (ff.sig_clk != cur_ff.sig_clk)
+ return false;
+ if (ff.pol_clk != cur_ff.pol_clk)
+ return false;
+ }
+ if (ff.has_ce) {
+ if (ff.sig_ce != cur_ff.sig_ce)
+ return false;
+ if (ff.pol_ce != cur_ff.pol_ce)
+ return false;
+ }
+ if (ff.has_aload) {
+ if (ff.sig_aload != cur_ff.sig_aload)
+ return false;
+ if (ff.pol_aload != cur_ff.pol_aload)
+ return false;
+ }
+ if (ff.has_srst) {
+ if (ff.sig_srst != cur_ff.sig_srst)
+ return false;
+ if (ff.pol_srst != cur_ff.pol_srst)
+ return false;
+ if (ff.has_ce && ff.ce_over_srst != cur_ff.ce_over_srst)
+ return false;
+ }
+ if (ff.has_arst) {
+ if (ff.sig_arst != cur_ff.sig_arst)
+ return false;
+ if (ff.pol_arst != cur_ff.pol_arst)
+ return false;
+ }
+ if (ff.has_sr) {
+ if (ff.pol_clr != cur_ff.pol_clr)
+ return false;
+ if (ff.pol_set != cur_ff.pol_set)
+ return false;
+ }
+ }
+
+ ff.width++;
+ ff.sig_d.append(cur_ff.sig_d[idx]);
+ ff.sig_ad.append(ff.has_aload ? cur_ff.sig_ad[idx] : State::Sx);
+ ff.sig_q.append(cur_ff.sig_q[idx]);
+ ff.sig_clr.append(ff.has_sr ? cur_ff.sig_clr[idx] : State::S0);
+ ff.sig_set.append(ff.has_sr ? cur_ff.sig_set[idx] : State::S0);
+ ff.val_arst.bits.push_back(ff.has_arst ? cur_ff.val_arst[idx] : State::Sx);
+ ff.val_srst.bits.push_back(ff.has_srst ? cur_ff.val_srst[idx] : State::Sx);
+ ff.val_init.bits.push_back(cur_ff.val_init[idx]);
+ found = true;
+ }
+
+ return found;
+}
+
+bool FfMergeHelper::find_input_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pair<Cell *, int>> &bits) {
+ ff = FfData(module, initvals, NEW_ID);
+ sigmap->apply(sig);
+
+ bool found = false;
+
+ pool<int> const_bits;
+
+ for (auto bit : sig)
+ {
+ if (bit.wire == NULL) {
+ const_bits.insert(ff.width);
+ ff.width++;
+ ff.sig_q.append(bit);
+ ff.sig_d.append(bit);
+ // These two will be fixed up later.
+ ff.sig_clr.append(State::Sx);
+ ff.sig_set.append(State::Sx);
+ ff.val_init.bits.push_back(bit.data);
+ ff.val_srst.bits.push_back(bit.data);
+ ff.val_arst.bits.push_back(bit.data);
+ continue;
+ }
+
+ if (!dff_driver.count(bit))
+ return false;
+
+ Cell *cell;
+ int idx;
+ std::tie(cell, idx) = dff_driver[bit];
+ bits.insert(std::make_pair(cell, idx));
+
+ FfData cur_ff(initvals, cell);
+
+ log_assert((*sigmap)(cur_ff.sig_q[idx]) == bit);
+
+ if (!found) {
+ ff.sig_clk = cur_ff.sig_clk;
+ ff.sig_ce = cur_ff.sig_ce;
+ ff.sig_aload = cur_ff.sig_aload;
+ ff.sig_srst = cur_ff.sig_srst;
+ ff.sig_arst = cur_ff.sig_arst;
+ ff.has_clk = cur_ff.has_clk;
+ ff.has_gclk = cur_ff.has_gclk;
+ ff.has_ce = cur_ff.has_ce;
+ ff.has_aload = cur_ff.has_aload;
+ ff.has_srst = cur_ff.has_srst;
+ ff.has_arst = cur_ff.has_arst;
+ ff.has_sr = cur_ff.has_sr;
+ ff.ce_over_srst = cur_ff.ce_over_srst;
+ ff.pol_clk = cur_ff.pol_clk;
+ ff.pol_ce = cur_ff.pol_ce;
+ ff.pol_aload = cur_ff.pol_aload;
+ ff.pol_arst = cur_ff.pol_arst;
+ ff.pol_srst = cur_ff.pol_srst;
+ ff.pol_clr = cur_ff.pol_clr;
+ ff.pol_set = cur_ff.pol_set;
+ } else {
+ if (ff.has_gclk != cur_ff.has_gclk)
+ return false;
+ if (ff.has_clk != cur_ff.has_clk)
+ return false;
+ if (ff.has_ce != cur_ff.has_ce)
+ return false;
+ if (ff.has_aload != cur_ff.has_aload)
+ return false;
+ if (ff.has_srst != cur_ff.has_srst)
+ return false;
+ if (ff.has_arst != cur_ff.has_arst)
+ return false;
+ if (ff.has_sr != cur_ff.has_sr)
+ return false;
+ if (ff.has_clk) {
+ if (ff.sig_clk != cur_ff.sig_clk)
+ return false;
+ if (ff.pol_clk != cur_ff.pol_clk)
+ return false;
+ }
+ if (ff.has_ce) {
+ if (ff.sig_ce != cur_ff.sig_ce)
+ return false;
+ if (ff.pol_ce != cur_ff.pol_ce)
+ return false;
+ }
+ if (ff.has_aload) {
+ if (ff.sig_aload != cur_ff.sig_aload)
+ return false;
+ if (ff.pol_aload != cur_ff.pol_aload)
+ return false;
+ }
+ if (ff.has_srst) {
+ if (ff.sig_srst != cur_ff.sig_srst)
+ return false;
+ if (ff.pol_srst != cur_ff.pol_srst)
+ return false;
+ if (ff.has_ce && ff.ce_over_srst != cur_ff.ce_over_srst)
+ return false;
+ }
+ if (ff.has_arst) {
+ if (ff.sig_arst != cur_ff.sig_arst)
+ return false;
+ if (ff.pol_arst != cur_ff.pol_arst)
+ return false;
+ }
+ if (ff.has_sr) {
+ if (ff.pol_clr != cur_ff.pol_clr)
+ return false;
+ if (ff.pol_set != cur_ff.pol_set)
+ return false;
+ }
+ }
+
+ ff.width++;
+ ff.sig_d.append((ff.has_clk || ff.has_gclk) ? cur_ff.sig_d[idx] : State::Sx);
+ ff.sig_ad.append(ff.has_aload ? cur_ff.sig_ad[idx] : State::Sx);
+ ff.sig_q.append(cur_ff.sig_q[idx]);
+ ff.sig_clr.append(ff.has_sr ? cur_ff.sig_clr[idx] : State::S0);
+ ff.sig_set.append(ff.has_sr ? cur_ff.sig_set[idx] : State::S0);
+ ff.val_arst.bits.push_back(ff.has_arst ? cur_ff.val_arst[idx] : State::Sx);
+ ff.val_srst.bits.push_back(ff.has_srst ? cur_ff.val_srst[idx] : State::Sx);
+ ff.val_init.bits.push_back(cur_ff.val_init[idx]);
+ found = true;
+ }
+
+ if (found && ff.has_sr) {
+ for (auto i: const_bits) {
+ if (ff.sig_d[i] == State::S0) {
+ ff.sig_set[i] = ff.pol_set ? State::S0 : State::S1;
+ } else if (ff.sig_d[i] == State::S1) {
+ ff.sig_clr[i] = ff.pol_clr ? State::S0 : State::S1;
+ }
+ }
+ }
+
+ return found;
+}
+
+
+void FfMergeHelper::remove_output_ff(const pool<std::pair<Cell *, int>> &bits) {
+ for (auto &it : bits) {
+ Cell *cell = it.first;
+ int idx = it.second;
+ SigSpec q = cell->getPort(ID::Q);
+ initvals->remove_init(q[idx]);
+ dff_driver.erase((*sigmap)(q[idx]));
+ q[idx] = module->addWire(stringf("$ffmerge_disconnected$%d", autoidx++));
+ cell->setPort(ID::Q, q);
+ }
+}
+
+void FfMergeHelper::mark_input_ff(const pool<std::pair<Cell *, int>> &bits) {
+ for (auto &it : bits) {
+ Cell *cell = it.first;
+ int idx = it.second;
+ if (cell->hasPort(ID::D)) {
+ SigSpec d = cell->getPort(ID::D);
+ // The user count was already at least 1
+ // (for the D port). Bump it as it is now connected
+ // to the merged-to cell as well. This suffices for
+ // it to not be considered for output merging.
+ sigbit_users_count[d[idx]]++;
+ }
+ }
+}
+
+void FfMergeHelper::set(FfInitVals *initvals_, RTLIL::Module *module_)
+{
+ clear();
+ initvals = initvals_;
+ sigmap = initvals->sigmap;
+ module = module_;
+
+ for (auto wire : module->wires()) {
+ if (wire->port_output)
+ for (auto bit : (*sigmap)(wire))
+ sigbit_users_count[bit]++;
+ }
+
+ for (auto cell : module->cells()) {
+ if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
+ if (cell->hasPort(ID::D)) {
+ SigSpec d = (*sigmap)(cell->getPort(ID::D));
+ for (int i = 0; i < GetSize(d); i++)
+ dff_sink[d[i]].insert(std::make_pair(cell, i));
+ }
+ SigSpec q = (*sigmap)(cell->getPort(ID::Q));
+ for (int i = 0; i < GetSize(q); i++)
+ dff_driver[q[i]] = std::make_pair(cell, i);
+ }
+ for (auto &conn : cell->connections())
+ if (!cell->known() || cell->input(conn.first))
+ for (auto bit : (*sigmap)(conn.second))
+ sigbit_users_count[bit]++;
+ }
+}
+
+void FfMergeHelper::clear() {
+ dff_driver.clear();
+ dff_sink.clear();
+ sigbit_users_count.clear();
+}
diff --git a/kernel/ffmerge.h b/kernel/ffmerge.h
new file mode 100644
index 000000000..5428da324
--- /dev/null
+++ b/kernel/ffmerge.h
@@ -0,0 +1,141 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * 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.
+ *
+ */
+
+#ifndef FFMERGE_H
+#define FFMERGE_H
+
+#include "kernel/ffinit.h"
+#include "kernel/ff.h"
+
+YOSYS_NAMESPACE_BEGIN
+
+// A helper class for passes that want to merge FFs on the input or output
+// of a cell into the cell itself.
+//
+// The procedure is:
+//
+// 1. Construct this class (at beginning of processing for a given module).
+// 2. For every considered cell:
+//
+// a. Call find_output_ff for every considered output.
+// b. Call find_input_ff for every considered input.
+// c. Look at the FF description returned (if any) from each call, reject
+// results that cannot be merged into given cell for any reason.
+// If both inputs and outputs are being merged, take care of FF bits that
+// are returned in both input and output results (a FF bit cannot be
+// merged to both). Decide on the final set of FF bits to merge.
+// d. Call remove_output_ff for every find_output_ff result that will be used
+// for merging. This removes the actual FF bits from design and from index.
+// e. Call mark_input_ff for every find_input_ff result that will be used
+// for merging. This updates the index disallowing further usage of these
+// FF bits for output FF merging, if they were eligible before. The actual
+// FF bits are still left in the design and can be merged into other inputs.
+// If the FF bits are not otherwise used, they will be removed by later
+// opt passes.
+// f. Merge the FFs into the cell.
+//
+// Note that, if both inputs and outputs are being considered for merging in
+// a single pass, the result may be nondeterministic (depending on cell iteration
+// order) because a given FF bit could be eligible for both input and output merge,
+// perhaps in different cells. For this reason, it may be a good idea to separate
+// input and output merging.
+
+struct FfMergeHelper
+{
+ const SigMap *sigmap;
+ RTLIL::Module *module;
+ FfInitVals *initvals;
+
+ dict<SigBit, std::pair<Cell*, int>> dff_driver;
+ dict<SigBit, pool<std::pair<Cell*, int>>> dff_sink;
+ dict<SigBit, int> sigbit_users_count;
+
+ // Returns true if all bits in sig are completely unused.
+ bool is_output_unused(RTLIL::SigSpec sig);
+
+ // Finds the FF to merge into a given cell output. Takes sig, which
+ // is the current cell output — it will be the sig_d of the found FF.
+ // If found, returns true, and fills the two output arguments.
+ //
+ // For every bit of sig, this function finds a FF bit that has
+ // the same sig_d, and fills the output FfData according to the FF
+ // bits found. This function will only consider FF bits that are
+ // the only user of the given sig bits — if any bit in sig is used
+ // by anything other than a single FF, this function will return false.
+ //
+ // The returned FfData structure does not correspond to any actual FF
+ // cell in the design — it is the amalgamation of extracted FF bits,
+ // possibly coming from several FF cells.
+ //
+ // If some of the bits in sig have no users at all, this function
+ // will accept them as well (and fill returned FfData with dummy values
+ // for the given bit, effectively synthesizing an unused FF bit of the
+ // appropriate type). However, if all bits in sig are completely
+ // unused, this function will fail and return false (having no idea
+ // what kind of FF to produce) — use the above helper if that case
+ // is important to handle.
+ //
+ // Note that this function does not remove the FF bits returned from
+ // the design — this is so that the caller can decide whether to accept
+ // this FF for merging or not. If the result is accepted,
+ // remove_output_ff should be called on the second output argument.
+ bool find_output_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pair<Cell *, int>> &bits);
+
+ // Like above, but returns a FF to merge into a given cell input. Takes
+ // sig_q, which is the current cell input — it will search for FFs with
+ // matching sig_q.
+ //
+ // As opposed to find_output_ff, this function doesn't care about usage
+ // counts, and may return FF bits that also have other fanout. This
+ // should not be a problem for input FF merging.
+ //
+ // As a special case, if some of the bits in sig_q are constant, this
+ // function will accept them as well, by synthesizing in-place
+ // a constant-input FF bit (with matching initial value and reset value).
+ // However, this will not work if the input is all-constant — if the caller
+ // cares about this case, it needs to check for it explicitely.
+ bool find_input_ff(RTLIL::SigSpec sig, FfData &ff, pool<std::pair<Cell *, int>> &bits);
+
+ // To be called on find_output_ff result that will be merged. This
+ // marks the given FF bits as used up (and not to be considered for
+ // further merging as inputs), and reconnects their Q ports to a dummy
+ // wire (since the wire previously connected there will now be driven
+ // by the merged-to cell instead).
+ void remove_output_ff(const pool<std::pair<Cell *, int>> &bits);
+
+ // To be called on find_input_ff result that will be merged. This
+ // marks the given FF bits as used, and disallows merging them as
+ // outputs. They can, however, still be merged as inputs again
+ // (perhaps for another cell).
+ void mark_input_ff(const pool<std::pair<Cell *, int>> &bits);
+
+ void set(FfInitVals *initvals_, RTLIL::Module *module_);
+
+ void clear();
+
+ FfMergeHelper(FfInitVals *initvals, RTLIL::Module *module) {
+ set(initvals, module);
+ }
+
+ FfMergeHelper() {}
+};
+
+YOSYS_NAMESPACE_END
+
+#endif
diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc
new file mode 100644
index 000000000..330c4d189
--- /dev/null
+++ b/kernel/fstdata.cc
@@ -0,0 +1,252 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2022 Miodrag Milanovic <micko@yosyshq.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 "kernel/fstdata.h"
+
+USING_YOSYS_NAMESPACE
+
+
+FstData::FstData(std::string filename) : ctx(nullptr)
+{
+ const std::vector<std::string> g_units = { "s", "ms", "us", "ns", "ps", "fs", "as", "zs" };
+ ctx = (fstReaderContext *)fstReaderOpen(filename.c_str());
+ if (!ctx)
+ log_error("Error opening '%s'\n", filename.c_str());
+ int scale = (int)fstReaderGetTimescale(ctx);
+ timescale = pow(10.0, scale);
+ timescale_str = "";
+ int unit = 0;
+ int zeros = 0;
+ if (scale > 0) {
+ zeros = scale;
+ } else {
+ if ((scale % 3) == 0) {
+ zeros = (-scale % 3);
+ unit = (-scale / 3);
+ } else {
+ zeros = 3 - (-scale % 3);
+ unit = (-scale / 3) + 1;
+ }
+ }
+ for (int i=0;i<zeros; i++) timescale_str += "0";
+ timescale_str += g_units[unit];
+ extractVarNames();
+}
+
+FstData::~FstData()
+{
+ if (ctx)
+ fstReaderClose(ctx);
+}
+
+uint64_t FstData::getStartTime() { return fstReaderGetStartTime(ctx); }
+
+uint64_t FstData::getEndTime() { return fstReaderGetEndTime(ctx); }
+
+fstHandle FstData::getHandle(std::string name) {
+ if (name_to_handle.find(name) != name_to_handle.end())
+ return name_to_handle[name];
+ else
+ return 0;
+};
+
+static std::string remove_spaces(std::string str)
+{
+ str.erase(std::remove(str.begin(), str.end(), ' '), str.end());
+ return str;
+}
+
+void FstData::extractVarNames()
+{
+ struct fstHier *h;
+ intptr_t snum = 0;
+
+ while ((h = fstReaderIterateHier(ctx))) {
+ switch (h->htyp) {
+ case FST_HT_SCOPE: {
+ snum++;
+ std::string fst_scope_name = fstReaderPushScope(ctx, h->u.scope.name, (void *)(snum));
+ scopes.push_back(fst_scope_name);
+ break;
+ }
+ case FST_HT_UPSCOPE: {
+ fstReaderPopScope(ctx);
+ snum = fstReaderGetCurrentScopeLen(ctx) ? (intptr_t)fstReaderGetCurrentScopeUserInfo(ctx) : 0;
+ break;
+ }
+ case FST_HT_VAR: {
+ FstVar var;
+ var.id = h->u.var.handle;
+ var.is_alias = h->u.var.is_alias;
+ var.name = remove_spaces(h->u.var.name);
+ var.scope = scopes.back();
+ var.width = h->u.var.length;
+ vars.push_back(var);
+ if (!var.is_alias)
+ handle_to_var[h->u.var.handle] = var;
+ std::string clean_name;
+ for(size_t i=0;i<strlen(h->u.var.name);i++)
+ {
+ char c = h->u.var.name[i];
+ if(c==' ') break;
+ clean_name += c;
+ }
+ if (clean_name[0]=='\\')
+ clean_name = clean_name.substr(1);
+ //log("adding %s.%s\n",var.scope.c_str(), clean_name.c_str());
+
+ name_to_handle[var.scope+"."+clean_name] = h->u.var.handle;
+ break;
+ }
+ }
+ }
+}
+
+static void reconstruct_edges_varlen(void *user_data, uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen)
+{
+ FstData *ptr = (FstData*)user_data;
+ ptr->reconstruct_edges_callback(pnt_time, pnt_facidx, pnt_value, plen);
+}
+
+static void reconstruct_edges(void *user_data, uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value)
+{
+ FstData *ptr = (FstData*)user_data;
+ uint32_t plen = (pnt_value) ? strlen((const char *)pnt_value) : 0;
+ ptr->reconstruct_edges_callback(pnt_time, pnt_facidx, pnt_value, plen);
+}
+
+void FstData::reconstruct_edges_callback(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t /* plen */)
+{
+ std::string val = std::string((const char *)pnt_value);
+ std::string prev = last_data[pnt_facidx];
+ if (pnt_time>=start_time) {
+ if (prev!="1" && val=="1")
+ edges.push_back(pnt_time);
+ if (prev!="0" && val=="0")
+ edges.push_back(pnt_time);
+ }
+ last_data[pnt_facidx] = val;
+}
+
+std::vector<uint64_t> FstData::getAllEdges(std::vector<fstHandle> &signal, uint64_t start, uint64_t end)
+{
+ start_time = start;
+ end_time = end;
+ last_data.clear();
+ for(auto &s : signal) {
+ last_data[s] = "x";
+ }
+ edges.clear();
+ fstReaderSetLimitTimeRange(ctx, start_time, end_time);
+ fstReaderClrFacProcessMaskAll(ctx);
+ for(const auto sig : signal)
+ fstReaderSetFacProcessMask(ctx,sig);
+ fstReaderIterBlocks2(ctx, reconstruct_edges, reconstruct_edges_varlen, this, nullptr);
+ return edges;
+}
+
+static void reconstruct_clb_varlen_attimes(void *user_data, uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen)
+{
+ FstData *ptr = (FstData*)user_data;
+ ptr->reconstruct_callback_attimes(pnt_time, pnt_facidx, pnt_value, plen);
+}
+
+static void reconstruct_clb_attimes(void *user_data, uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value)
+{
+ FstData *ptr = (FstData*)user_data;
+ uint32_t plen = (pnt_value) ? strlen((const char *)pnt_value) : 0;
+ ptr->reconstruct_callback_attimes(pnt_time, pnt_facidx, pnt_value, plen);
+}
+
+void FstData::reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t /* plen */)
+{
+ if (sample_times_ndx >= sample_times.size()) return;
+
+ uint64_t time = sample_times[sample_times_ndx];
+ // if we are past the timestamp
+ if (pnt_time > time) {
+ for (auto const& c : last_data)
+ {
+ handle_to_data[c.first].push_back(std::make_pair(time,c.second));
+ size_t index = handle_to_data[c.first].size() - 1;
+ time_to_index[c.first][time] = index;
+ }
+ sample_times_ndx++;
+ }
+ // always update last_data
+ last_data[pnt_facidx] = std::string((const char *)pnt_value);
+}
+
+void FstData::reconstructAtTimes(std::vector<fstHandle> &signal, std::vector<uint64_t> time)
+{
+ handle_to_data.clear();
+ time_to_index.clear();
+ last_data.clear();
+ sample_times_ndx = 0;
+ sample_times = time;
+ fstReaderSetUnlimitedTimeRange(ctx);
+ fstReaderClrFacProcessMaskAll(ctx);
+ for(const auto sig : signal)
+ fstReaderSetFacProcessMask(ctx,sig);
+ fstReaderIterBlocks2(ctx, reconstruct_clb_attimes, reconstruct_clb_varlen_attimes, this, nullptr);
+
+ if (time_to_index[signal.back()].count(time.back())==0) {
+ for (auto const& c : last_data)
+ {
+ handle_to_data[c.first].push_back(std::make_pair(time.back(),c.second));
+ size_t index = handle_to_data[c.first].size() - 1;
+ time_to_index[c.first][time.back()] = index;
+ }
+ }
+}
+
+void FstData::reconstructAllAtTimes(std::vector<uint64_t> time)
+{
+ handle_to_data.clear();
+ time_to_index.clear();
+ last_data.clear();
+ sample_times_ndx = 0;
+ sample_times = time;
+
+ fstReaderSetUnlimitedTimeRange(ctx);
+ fstReaderSetFacProcessMaskAll(ctx);
+ fstReaderIterBlocks2(ctx, reconstruct_clb_attimes, reconstruct_clb_varlen_attimes, this, nullptr);
+
+ if (time_to_index[1].count(time.back())==0) {
+ for (auto const& c : last_data)
+ {
+ handle_to_data[c.first].push_back(std::make_pair(time.back(),c.second));
+ size_t index = handle_to_data[c.first].size() - 1;
+ time_to_index[c.first][time.back()] = index;
+ }
+ }
+}
+
+std::string FstData::valueAt(fstHandle signal, uint64_t time)
+{
+ if (handle_to_data.find(signal) == handle_to_data.end())
+ log_error("Signal id %d not found\n", (int)signal);
+ auto &data = handle_to_data[signal];
+ if (time_to_index[signal].count(time)!=0) {
+ size_t index = time_to_index[signal][time];
+ return data.at(index).second;
+ } else {
+ log_error("No data for signal %d at time %d\n", (int)signal, (int)time);
+ }
+}
diff --git a/kernel/fstdata.h b/kernel/fstdata.h
new file mode 100644
index 000000000..c069ff5e5
--- /dev/null
+++ b/kernel/fstdata.h
@@ -0,0 +1,81 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2022 Miodrag Milanovic <micko@yosyshq.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.
+ *
+ */
+
+#ifndef FSTDATA_H
+#define FSTDATA_H
+
+#include "kernel/yosys.h"
+#include "libs/fst/fstapi.h"
+
+YOSYS_NAMESPACE_BEGIN
+
+struct FstVar
+{
+ fstHandle id;
+ std::string name;
+ bool is_alias;
+ std::string scope;
+ int width;
+};
+
+class FstData
+{
+ public:
+ FstData(std::string filename);
+ ~FstData();
+
+ uint64_t getStartTime();
+ uint64_t getEndTime();
+
+ std::vector<FstVar>& getVars() { return vars; };
+
+ void reconstruct_edges_callback(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen);
+ std::vector<uint64_t> getAllEdges(std::vector<fstHandle> &signal, uint64_t start_time, uint64_t end_time);
+
+ void reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen);
+ void reconstructAtTimes(std::vector<fstHandle> &signal,std::vector<uint64_t> time);
+ void reconstructAllAtTimes(std::vector<uint64_t> time);
+
+ std::string valueAt(fstHandle signal, uint64_t time);
+ fstHandle getHandle(std::string name);
+ double getTimescale() { return timescale; }
+ const char *getTimescaleString() { return timescale_str.c_str(); }
+private:
+ void extractVarNames();
+
+ struct fstReaderContext *ctx;
+ std::vector<std::string> scopes;
+ std::vector<FstVar> vars;
+ std::map<fstHandle, FstVar> handle_to_var;
+ std::map<std::string, fstHandle> name_to_handle;
+ std::map<fstHandle, std::vector<std::pair<uint64_t, std::string>>> handle_to_data;
+ std::map<fstHandle, std::string> last_data;
+ std::map<fstHandle, std::map<uint64_t, size_t>> time_to_index;
+ std::vector<uint64_t> sample_times;
+ size_t sample_times_ndx;
+ double timescale;
+ std::string timescale_str;
+ uint64_t start_time;
+ uint64_t end_time;
+ std::vector<uint64_t> edges;
+};
+
+YOSYS_NAMESPACE_END
+
+#endif
diff --git a/kernel/hashlib.h b/kernel/hashlib.h
index a523afadd..0c9f25287 100644
--- a/kernel/hashlib.h
+++ b/kernel/hashlib.h
@@ -6,7 +6,7 @@
// means.
// -------------------------------------------------------
-// Written by Clifford Wolf <clifford@clifford.at> in 2014
+// Written by Claire Xenia Wolf <claire@yosyshq.com> in 2014
// -------------------------------------------------------
#ifndef HASHLIB_H
@@ -66,6 +66,12 @@ struct hash_int_ops {
}
};
+template<> struct hash_ops<bool> : hash_int_ops
+{
+ static inline unsigned int hash(bool a) {
+ return a ? 1 : 0;
+ }
+};
template<> struct hash_ops<int32_t> : hash_int_ops
{
static inline unsigned int hash(int32_t a) {
diff --git a/kernel/log.cc b/kernel/log.cc
index 41e91119e..4bcce3b28 100644
--- a/kernel/log.cc
+++ b/kernel/log.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -71,8 +71,6 @@ int string_buf_index = -1;
static struct timeval initial_tv = { 0, 0 };
static bool next_print_log = false;
static int log_newline_count = 0;
-static bool check_expected_logs = true;
-static bool display_error_log_msg = true;
static void log_id_cache_clear()
{
@@ -339,8 +337,7 @@ static void logv_error_with_prefix(const char *prefix,
f = stderr;
log_last_error = vstringf(format, ap);
- if (display_error_log_msg)
- log("%s%s", prefix, log_last_error.c_str());
+ log("%s%s", prefix, log_last_error.c_str());
log_flush();
log_make_debug = bak_log_make_debug;
@@ -349,8 +346,7 @@ static void logv_error_with_prefix(const char *prefix,
if (YS_REGEX_NS::regex_search(log_last_error, item.second.pattern))
item.second.current_count++;
- if (check_expected_logs)
- log_check_expected();
+ log_check_expected();
if (log_error_atexit)
log_error_atexit();
@@ -667,9 +663,14 @@ void log_wire(RTLIL::Wire *wire, std::string indent)
void log_check_expected()
{
- check_expected_logs = false;
+ // copy out all of the expected logs so that they cannot be re-checked
+ // or match against themselves
+ dict<std::string, LogExpectedItem> expect_log, expect_warning, expect_error;
+ std::swap(expect_warning, log_expect_warning);
+ std::swap(expect_log, log_expect_log);
+ std::swap(expect_error, log_expect_error);
- for (auto &item : log_expect_warning) {
+ for (auto &item : expect_warning) {
if (item.second.current_count == 0) {
log_warn_regexes.clear();
log_error("Expected warning pattern '%s' not found !\n", item.first.c_str());
@@ -681,7 +682,7 @@ void log_check_expected()
}
}
- for (auto &item : log_expect_log) {
+ for (auto &item : expect_log) {
if (item.second.current_count == 0) {
log_warn_regexes.clear();
log_error("Expected log pattern '%s' not found !\n", item.first.c_str());
@@ -693,7 +694,7 @@ void log_check_expected()
}
}
- for (auto &item : log_expect_error)
+ for (auto &item : expect_error)
if (item.second.current_count == item.second.expected_count) {
log_warn_regexes.clear();
log("Expected error pattern '%s' found !!!\n", item.first.c_str());
@@ -705,7 +706,6 @@ void log_check_expected()
_Exit(0);
#endif
} else {
- display_error_log_msg = false;
log_warn_regexes.clear();
log_error("Expected error pattern '%s' not found !\n", item.first.c_str());
}
diff --git a/kernel/log.h b/kernel/log.h
index 8981c4cde..ea14028dd 100644
--- a/kernel/log.h
+++ b/kernel/log.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -24,9 +24,29 @@
#include <time.h>
-// In GCC 4.8 std::regex is not working correctlty, in order to make features
-// using regular expressions to work replacement regex library is used
-#if defined(__GNUC__) && !defined( __clang__) && ( __GNUC__ == 4 && __GNUC_MINOR__ <= 8)
+// In the libstdc++ headers that are provided by GCC 4.8, std::regex is not
+// working correctly. In order to make features using regular expressions
+// work, a replacement regex library is used. Just checking for GCC version
+// is not enough though, because at least on RHEL7/CentOS7 even when compiling
+// with Clang instead of GCC, the GCC 4.8 headers are still used for std::regex.
+// We have to check the version of the libstdc++ headers specifically, not the
+// compiler version. GCC headers of libstdc++ before version 3.4 define
+// __GLIBCPP__, later versions define __GLIBCXX__. GCC 7 and newer additionaly
+// define _GLIBCXX_RELEASE with a version number.
+// Include limits std C++ header, so we get the version macros defined:
+#if defined(__cplusplus)
+# include <limits>
+#endif
+// Check if libstdc++ is from GCC
+#if defined(__GLIBCPP__) || defined(__GLIBCXX__)
+// Check if version could be 4.8 or lower (this also matches for some 4.9 and
+// 5.0 releases). See:
+// https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html#abi.versioning
+# if !defined(_GLIBCXX_RELEASE) && (defined(__GLIBCPP__) || __GLIBCXX__ <= 20150623)
+# define YS_HAS_BAD_STD_REGEX
+# endif
+#endif
+#if defined(YS_HAS_BAD_STD_REGEX)
#include <boost/xpressive/xpressive.hpp>
#define YS_REGEX_TYPE boost::xpressive::sregex
#define YS_REGEX_MATCH_TYPE boost::xpressive::smatch
diff --git a/kernel/macc.h b/kernel/macc.h
index d216e6772..e4e1ebf52 100644
--- a/kernel/macc.h
+++ b/kernel/macc.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/kernel/mem.cc b/kernel/mem.cc
index 0301a913c..059f8f934 100644
--- a/kernel/mem.cc
+++ b/kernel/mem.cc
@@ -18,6 +18,7 @@
*/
#include "kernel/mem.h"
+#include "kernel/ff.h"
USING_YOSYS_NAMESPACE
@@ -52,6 +53,67 @@ void Mem::remove() {
}
void Mem::emit() {
+ check();
+ std::vector<int> rd_left;
+ for (int i = 0; i < GetSize(rd_ports); i++) {
+ auto &port = rd_ports[i];
+ if (port.removed) {
+ if (port.cell) {
+ module->remove(port.cell);
+ }
+ } else {
+ rd_left.push_back(i);
+ }
+ }
+ std::vector<int> wr_left;
+ for (int i = 0; i < GetSize(wr_ports); i++) {
+ auto &port = wr_ports[i];
+ if (port.removed) {
+ if (port.cell) {
+ module->remove(port.cell);
+ }
+ } else {
+ wr_left.push_back(i);
+ }
+ }
+ std::vector<int> init_left;
+ for (int i = 0; i < GetSize(inits); i++) {
+ auto &init = inits[i];
+ if (init.removed) {
+ if (init.cell) {
+ module->remove(init.cell);
+ }
+ } else {
+ init_left.push_back(i);
+ }
+ }
+ for (int i = 0; i < GetSize(rd_left); i++)
+ if (i != rd_left[i])
+ std::swap(rd_ports[i], rd_ports[rd_left[i]]);
+ rd_ports.resize(GetSize(rd_left));
+ for (int i = 0; i < GetSize(wr_left); i++)
+ if (i != wr_left[i])
+ std::swap(wr_ports[i], wr_ports[wr_left[i]]);
+ wr_ports.resize(GetSize(wr_left));
+ for (int i = 0; i < GetSize(init_left); i++)
+ if (i != init_left[i])
+ std::swap(inits[i], inits[init_left[i]]);
+ inits.resize(GetSize(init_left));
+
+ for (auto &port : rd_ports) {
+ for (int i = 0; i < GetSize(wr_left); i++) {
+ port.transparency_mask[i] = port.transparency_mask[wr_left[i]];
+ port.collision_x_mask[i] = port.collision_x_mask[wr_left[i]];
+ }
+ port.transparency_mask.resize(GetSize(wr_left));
+ port.collision_x_mask.resize(GetSize(wr_left));
+ }
+ for (auto &port : wr_ports) {
+ for (int i = 0; i < GetSize(wr_left); i++)
+ port.priority_mask[i] = port.priority_mask[wr_left[i]];
+ port.priority_mask.resize(GetSize(wr_left));
+ }
+
if (packed) {
if (mem) {
module->memories.erase(mem->name);
@@ -61,54 +123,90 @@ void Mem::emit() {
if (!cell) {
if (memid.empty())
memid = NEW_ID;
- cell = module->addCell(memid, ID($mem));
+ cell = module->addCell(memid, ID($mem_v2));
}
+ cell->type = ID($mem_v2);
cell->attributes = attributes;
cell->parameters[ID::MEMID] = Const(memid.str());
cell->parameters[ID::WIDTH] = Const(width);
cell->parameters[ID::OFFSET] = Const(start_offset);
cell->parameters[ID::SIZE] = Const(size);
- cell->parameters[ID::RD_PORTS] = Const(GetSize(rd_ports));
- cell->parameters[ID::WR_PORTS] = Const(GetSize(wr_ports));
- Const rd_clk_enable, rd_clk_polarity, rd_transparent;
- Const wr_clk_enable, wr_clk_polarity;
+ Const rd_wide_continuation, rd_clk_enable, rd_clk_polarity, rd_transparency_mask, rd_collision_x_mask;
+ Const wr_wide_continuation, wr_clk_enable, wr_clk_polarity, wr_priority_mask;
+ Const rd_ce_over_srst, rd_arst_value, rd_srst_value, rd_init_value;
SigSpec rd_clk, rd_en, rd_addr, rd_data;
SigSpec wr_clk, wr_en, wr_addr, wr_data;
+ SigSpec rd_arst, rd_srst;
int abits = 0;
for (auto &port : rd_ports)
abits = std::max(abits, GetSize(port.addr));
for (auto &port : wr_ports)
abits = std::max(abits, GetSize(port.addr));
cell->parameters[ID::ABITS] = Const(abits);
+ std::vector<int> wr_port_xlat;
+ for (int i = 0; i < GetSize(wr_ports); i++)
+ for (int j = 0; j < (1 << wr_ports[i].wide_log2); j++)
+ wr_port_xlat.push_back(i);
for (auto &port : rd_ports) {
if (port.cell) {
module->remove(port.cell);
port.cell = nullptr;
}
- rd_clk_enable.bits.push_back(State(port.clk_enable));
- rd_clk_polarity.bits.push_back(State(port.clk_polarity));
- rd_transparent.bits.push_back(State(port.transparent));
- rd_clk.append(port.clk);
- log_assert(GetSize(port.clk) == 1);
- rd_en.append(port.en);
- log_assert(GetSize(port.en) == 1);
- SigSpec addr = port.addr;
- addr.extend_u0(abits, false);
- rd_addr.append(addr);
- log_assert(GetSize(addr) == abits);
+ for (int sub = 0; sub < (1 << port.wide_log2); sub++)
+ {
+ rd_wide_continuation.bits.push_back(State(sub != 0));
+ rd_clk_enable.bits.push_back(State(port.clk_enable));
+ rd_clk_polarity.bits.push_back(State(port.clk_polarity));
+ rd_ce_over_srst.bits.push_back(State(port.ce_over_srst));
+ rd_clk.append(port.clk);
+ rd_arst.append(port.arst);
+ rd_srst.append(port.srst);
+ rd_en.append(port.en);
+ SigSpec addr = port.sub_addr(sub);
+ addr.extend_u0(abits, false);
+ rd_addr.append(addr);
+ log_assert(GetSize(addr) == abits);
+ for (auto idx : wr_port_xlat) {
+ rd_transparency_mask.bits.push_back(State(bool(port.transparency_mask[idx])));
+ rd_collision_x_mask.bits.push_back(State(bool(port.collision_x_mask[idx])));
+ }
+ }
rd_data.append(port.data);
- log_assert(GetSize(port.data) == width);
+ for (auto &bit : port.arst_value)
+ rd_arst_value.bits.push_back(bit);
+ for (auto &bit : port.srst_value)
+ rd_srst_value.bits.push_back(bit);
+ for (auto &bit : port.init_value)
+ rd_init_value.bits.push_back(bit);
}
if (rd_ports.empty()) {
+ rd_wide_continuation = State::S0;
rd_clk_enable = State::S0;
rd_clk_polarity = State::S0;
- rd_transparent = State::S0;
+ rd_ce_over_srst = State::S0;
+ rd_arst_value = State::S0;
+ rd_srst_value = State::S0;
+ rd_init_value = State::S0;
+ }
+ if (rd_ports.empty() || wr_ports.empty()) {
+ rd_transparency_mask = State::S0;
+ rd_collision_x_mask = State::S0;
}
+ cell->parameters[ID::RD_PORTS] = Const(GetSize(rd_clk));
cell->parameters[ID::RD_CLK_ENABLE] = rd_clk_enable;
cell->parameters[ID::RD_CLK_POLARITY] = rd_clk_polarity;
- cell->parameters[ID::RD_TRANSPARENT] = rd_transparent;
+ cell->parameters[ID::RD_TRANSPARENCY_MASK] = rd_transparency_mask;
+ cell->parameters[ID::RD_COLLISION_X_MASK] = rd_collision_x_mask;
+ cell->parameters[ID::RD_WIDE_CONTINUATION] = rd_wide_continuation;
+ cell->parameters[ID::RD_CE_OVER_SRST] = rd_ce_over_srst;
+ cell->parameters[ID::RD_ARST_VALUE] = rd_arst_value;
+ cell->parameters[ID::RD_SRST_VALUE] = rd_srst_value;
+ cell->parameters[ID::RD_INIT_VALUE] = rd_init_value;
+ cell->parameters.erase(ID::RD_TRANSPARENT);
cell->setPort(ID::RD_CLK, rd_clk);
cell->setPort(ID::RD_EN, rd_en);
+ cell->setPort(ID::RD_ARST, rd_arst);
+ cell->setPort(ID::RD_SRST, rd_srst);
cell->setPort(ID::RD_ADDR, rd_addr);
cell->setPort(ID::RD_DATA, rd_data);
for (auto &port : wr_ports) {
@@ -116,25 +214,33 @@ void Mem::emit() {
module->remove(port.cell);
port.cell = nullptr;
}
- wr_clk_enable.bits.push_back(State(port.clk_enable));
- wr_clk_polarity.bits.push_back(State(port.clk_polarity));
- wr_clk.append(port.clk);
- log_assert(GetSize(port.clk) == 1);
+ for (int sub = 0; sub < (1 << port.wide_log2); sub++)
+ {
+ wr_wide_continuation.bits.push_back(State(sub != 0));
+ wr_clk_enable.bits.push_back(State(port.clk_enable));
+ wr_clk_polarity.bits.push_back(State(port.clk_polarity));
+ wr_clk.append(port.clk);
+ for (auto idx : wr_port_xlat)
+ wr_priority_mask.bits.push_back(State(bool(port.priority_mask[idx])));
+ SigSpec addr = port.sub_addr(sub);
+ addr.extend_u0(abits, false);
+ wr_addr.append(addr);
+ log_assert(GetSize(addr) == abits);
+ }
wr_en.append(port.en);
- log_assert(GetSize(port.en) == width);
- SigSpec addr = port.addr;
- addr.extend_u0(abits, false);
- wr_addr.append(addr);
- log_assert(GetSize(addr) == abits);
wr_data.append(port.data);
- log_assert(GetSize(port.data) == width);
}
if (wr_ports.empty()) {
+ wr_wide_continuation = State::S0;
wr_clk_enable = State::S0;
wr_clk_polarity = State::S0;
+ wr_priority_mask = State::S0;
}
+ cell->parameters[ID::WR_PORTS] = Const(GetSize(wr_clk));
cell->parameters[ID::WR_CLK_ENABLE] = wr_clk_enable;
cell->parameters[ID::WR_CLK_POLARITY] = wr_clk_polarity;
+ cell->parameters[ID::WR_PRIORITY_MASK] = wr_priority_mask;
+ cell->parameters[ID::WR_WIDE_CONTINUATION] = wr_wide_continuation;
cell->setPort(ID::WR_CLK, wr_clk);
cell->setPort(ID::WR_EN, wr_en);
cell->setPort(ID::WR_ADDR, wr_addr);
@@ -161,30 +267,46 @@ void Mem::emit() {
mem->width = width;
mem->start_offset = start_offset;
mem->size = size;
+ mem->attributes = attributes;
for (auto &port : rd_ports) {
if (!port.cell)
- port.cell = module->addCell(NEW_ID, ID($memrd));
+ port.cell = module->addCell(NEW_ID, ID($memrd_v2));
+ port.cell->type = ID($memrd_v2);
+ port.cell->attributes = port.attributes;
port.cell->parameters[ID::MEMID] = memid.str();
port.cell->parameters[ID::ABITS] = GetSize(port.addr);
- port.cell->parameters[ID::WIDTH] = width;
+ port.cell->parameters[ID::WIDTH] = width << port.wide_log2;
port.cell->parameters[ID::CLK_ENABLE] = port.clk_enable;
port.cell->parameters[ID::CLK_POLARITY] = port.clk_polarity;
- port.cell->parameters[ID::TRANSPARENT] = port.transparent;
+ port.cell->parameters[ID::CE_OVER_SRST] = port.ce_over_srst;
+ port.cell->parameters[ID::ARST_VALUE] = port.arst_value;
+ port.cell->parameters[ID::SRST_VALUE] = port.srst_value;
+ port.cell->parameters[ID::INIT_VALUE] = port.init_value;
+ port.cell->parameters[ID::TRANSPARENCY_MASK] = port.transparency_mask;
+ port.cell->parameters[ID::COLLISION_X_MASK] = port.collision_x_mask;
+ port.cell->parameters.erase(ID::TRANSPARENT);
port.cell->setPort(ID::CLK, port.clk);
port.cell->setPort(ID::EN, port.en);
+ port.cell->setPort(ID::ARST, port.arst);
+ port.cell->setPort(ID::SRST, port.srst);
port.cell->setPort(ID::ADDR, port.addr);
port.cell->setPort(ID::DATA, port.data);
}
int idx = 0;
for (auto &port : wr_ports) {
if (!port.cell)
- port.cell = module->addCell(NEW_ID, ID($memwr));
+ port.cell = module->addCell(NEW_ID, ID($memwr_v2));
+ port.cell->type = ID($memwr_v2);
+ port.cell->attributes = port.attributes;
+ if (port.cell->parameters.count(ID::PRIORITY))
+ port.cell->parameters.erase(ID::PRIORITY);
port.cell->parameters[ID::MEMID] = memid.str();
port.cell->parameters[ID::ABITS] = GetSize(port.addr);
- port.cell->parameters[ID::WIDTH] = width;
+ port.cell->parameters[ID::WIDTH] = width << port.wide_log2;
port.cell->parameters[ID::CLK_ENABLE] = port.clk_enable;
port.cell->parameters[ID::CLK_POLARITY] = port.clk_polarity;
- port.cell->parameters[ID::PRIORITY] = idx++;
+ port.cell->parameters[ID::PORTID] = idx++;
+ port.cell->parameters[ID::PRIORITY_MASK] = port.priority_mask;
port.cell->setPort(ID::CLK, port.clk);
port.cell->setPort(ID::EN, port.en);
port.cell->setPort(ID::ADDR, port.addr);
@@ -192,8 +314,12 @@ void Mem::emit() {
}
idx = 0;
for (auto &init : inits) {
+ bool v2 = !init.en.is_fully_ones();
if (!init.cell)
- init.cell = module->addCell(NEW_ID, ID($meminit));
+ init.cell = module->addCell(NEW_ID, v2 ? ID($meminit_v2) : ID($meminit));
+ else
+ init.cell->type = v2 ? ID($meminit_v2) : ID($meminit);
+ init.cell->attributes = init.attributes;
init.cell->parameters[ID::MEMID] = memid.str();
init.cell->parameters[ID::ABITS] = GetSize(init.addr);
init.cell->parameters[ID::WIDTH] = width;
@@ -201,42 +327,185 @@ void Mem::emit() {
init.cell->parameters[ID::PRIORITY] = idx++;
init.cell->setPort(ID::ADDR, init.addr);
init.cell->setPort(ID::DATA, init.data);
+ if (v2)
+ init.cell->setPort(ID::EN, init.en);
+ else
+ init.cell->unsetPort(ID::EN);
}
}
}
-void Mem::remove_wr_port(int idx) {
- if (wr_ports[idx].cell) {
- module->remove(wr_ports[idx].cell);
- }
- wr_ports.erase(wr_ports.begin() + idx);
+void Mem::clear_inits() {
+ for (auto &init : inits)
+ init.removed = true;
}
-void Mem::remove_rd_port(int idx) {
- if (rd_ports[idx].cell) {
- module->remove(rd_ports[idx].cell);
+void Mem::coalesce_inits() {
+ // start address -> end address
+ std::map<int, int> chunks;
+ // Figure out chunk boundaries.
+ for (auto &init : inits) {
+ if (init.removed)
+ continue;
+ bool valid = false;
+ for (auto bit : init.en)
+ if (bit == State::S1)
+ valid = true;
+ if (!valid) {
+ init.removed = true;
+ continue;
+ }
+ int addr = init.addr.as_int();
+ int addr_e = addr + GetSize(init.data) / width;
+ auto it_e = chunks.upper_bound(addr_e);
+ auto it = it_e;
+ while (it != chunks.begin()) {
+ --it;
+ if (it->second < addr) {
+ ++it;
+ break;
+ }
+ }
+ if (it == it_e) {
+ // No overlapping inits — add this one to index.
+ chunks[addr] = addr_e;
+ } else {
+ // We have an overlap — all chunks in the [it, it_e)
+ // range will be merged with this init.
+ if (it->first < addr)
+ addr = it->first;
+ auto it_last = it_e;
+ it_last--;
+ if (it_last->second > addr_e)
+ addr_e = it_last->second;
+ chunks.erase(it, it_e);
+ chunks[addr] = addr_e;
+ }
+ }
+ // Group inits by the chunk they belong to.
+ dict<int, std::vector<int>> inits_by_chunk;
+ for (int i = 0; i < GetSize(inits); i++) {
+ auto &init = inits[i];
+ if (init.removed)
+ continue;
+ auto it = chunks.upper_bound(init.addr.as_int());
+ --it;
+ inits_by_chunk[it->first].push_back(i);
+ int addr = init.addr.as_int();
+ int addr_e = addr + GetSize(init.data) / width;
+ log_assert(addr >= it->first && addr_e <= it->second);
+ }
+ // Process each chunk.
+ for (auto &it : inits_by_chunk) {
+ int caddr = it.first;
+ int caddr_e = chunks[caddr];
+ auto &chunk_inits = it.second;
+ if (GetSize(chunk_inits) == 1) {
+ auto &init = inits[chunk_inits[0]];
+ if (!init.en.is_fully_ones()) {
+ for (int i = 0; i < GetSize(init.data); i++)
+ if (init.en[i % width] != State::S1)
+ init.data[i] = State::Sx;
+ init.en = Const(State::S1, width);
+ }
+ continue;
+ }
+ Const cdata(State::Sx, (caddr_e - caddr) * width);
+ for (int idx : chunk_inits) {
+ auto &init = inits[idx];
+ int offset = (init.addr.as_int() - caddr) * width;
+ log_assert(offset >= 0);
+ log_assert(offset + GetSize(init.data) <= GetSize(cdata));
+ for (int i = 0; i < GetSize(init.data); i++)
+ if (init.en[i % width] == State::S1)
+ cdata.bits[i+offset] = init.data.bits[i];
+ init.removed = true;
+ }
+ MemInit new_init;
+ new_init.addr = caddr;
+ new_init.data = cdata;
+ new_init.en = Const(State::S1, width);
+ inits.push_back(new_init);
}
- rd_ports.erase(rd_ports.begin() + idx);
-}
-
-void Mem::clear_inits() {
- for (auto &init : inits)
- if (init.cell)
- module->remove(init.cell);
- inits.clear();
}
Const Mem::get_init_data() const {
Const init_data(State::Sx, width * size);
for (auto &init : inits) {
+ if (init.removed)
+ continue;
int offset = (init.addr.as_int() - start_offset) * width;
for (int i = 0; i < GetSize(init.data); i++)
- if (0 <= i+offset && i+offset < GetSize(init_data))
+ if (0 <= i+offset && i+offset < GetSize(init_data) && init.en[i % width] == State::S1)
init_data.bits[i+offset] = init.data.bits[i];
}
return init_data;
}
+void Mem::check() {
+ int max_wide_log2 = 0;
+ for (auto &port : rd_ports) {
+ if (port.removed)
+ continue;
+ log_assert(GetSize(port.clk) == 1);
+ log_assert(GetSize(port.en) == 1);
+ log_assert(GetSize(port.arst) == 1);
+ log_assert(GetSize(port.srst) == 1);
+ log_assert(GetSize(port.data) == (width << port.wide_log2));
+ log_assert(GetSize(port.init_value) == (width << port.wide_log2));
+ log_assert(GetSize(port.arst_value) == (width << port.wide_log2));
+ log_assert(GetSize(port.srst_value) == (width << port.wide_log2));
+ if (!port.clk_enable) {
+ log_assert(port.en == State::S1);
+ log_assert(port.arst == State::S0);
+ log_assert(port.srst == State::S0);
+ }
+ for (int j = 0; j < port.wide_log2; j++) {
+ log_assert(port.addr[j] == State::S0);
+ }
+ max_wide_log2 = std::max(max_wide_log2, port.wide_log2);
+ log_assert(GetSize(port.transparency_mask) == GetSize(wr_ports));
+ log_assert(GetSize(port.collision_x_mask) == GetSize(wr_ports));
+ for (int j = 0; j < GetSize(wr_ports); j++) {
+ auto &wport = wr_ports[j];
+ if ((port.transparency_mask[j] || port.collision_x_mask[j]) && !wport.removed) {
+ log_assert(port.clk_enable);
+ log_assert(wport.clk_enable);
+ log_assert(port.clk == wport.clk);
+ log_assert(port.clk_polarity == wport.clk_polarity);
+ }
+ log_assert(!port.transparency_mask[j] || !port.collision_x_mask[j]);
+ }
+ }
+ for (int i = 0; i < GetSize(wr_ports); i++) {
+ auto &port = wr_ports[i];
+ if (port.removed)
+ continue;
+ log_assert(GetSize(port.clk) == 1);
+ log_assert(GetSize(port.en) == (width << port.wide_log2));
+ log_assert(GetSize(port.data) == (width << port.wide_log2));
+ for (int j = 0; j < port.wide_log2; j++) {
+ log_assert(port.addr[j] == State::S0);
+ }
+ max_wide_log2 = std::max(max_wide_log2, port.wide_log2);
+ log_assert(GetSize(port.priority_mask) == GetSize(wr_ports));
+ for (int j = 0; j < GetSize(wr_ports); j++) {
+ auto &wport = wr_ports[j];
+ if (port.priority_mask[j] && !wport.removed) {
+ log_assert(j < i);
+ log_assert(port.clk_enable == wport.clk_enable);
+ if (port.clk_enable) {
+ log_assert(port.clk == wport.clk);
+ log_assert(port.clk_polarity == wport.clk_polarity);
+ }
+ }
+ }
+ }
+ int mask = (1 << max_wide_log2) - 1;
+ log_assert(!(start_offset & mask));
+ log_assert(!(size & mask));
+}
+
namespace {
struct MemIndex {
@@ -245,11 +514,11 @@ namespace {
dict<IdString, pool<Cell *>> inits;
MemIndex (Module *module) {
for (auto cell: module->cells()) {
- if (cell->type == ID($memwr))
+ if (cell->type.in(ID($memwr), ID($memwr_v2)))
wr_ports[cell->parameters.at(ID::MEMID).decode_string()].insert(cell);
- else if (cell->type == ID($memrd))
+ else if (cell->type.in(ID($memrd), ID($memrd_v2)))
rd_ports[cell->parameters.at(ID::MEMID).decode_string()].insert(cell);
- else if (cell->type == ID($meminit))
+ else if (cell->type.in(ID($meminit), ID($meminit_v2)))
inits[cell->parameters.at(ID::MEMID).decode_string()].insert(cell);
}
}
@@ -260,25 +529,56 @@ namespace {
res.packed = false;
res.mem = mem;
res.attributes = mem->attributes;
+ std::vector<bool> rd_transparent;
+ std::vector<int> wr_portid;
if (index.rd_ports.count(mem->name)) {
for (auto cell : index.rd_ports.at(mem->name)) {
MemRd mrd;
+ bool is_compat = cell->type == ID($memrd);
mrd.cell = cell;
mrd.attributes = cell->attributes;
mrd.clk_enable = cell->parameters.at(ID::CLK_ENABLE).as_bool();
mrd.clk_polarity = cell->parameters.at(ID::CLK_POLARITY).as_bool();
- mrd.transparent = cell->parameters.at(ID::TRANSPARENT).as_bool();
mrd.clk = cell->getPort(ID::CLK);
mrd.en = cell->getPort(ID::EN);
mrd.addr = cell->getPort(ID::ADDR);
mrd.data = cell->getPort(ID::DATA);
+ mrd.wide_log2 = ceil_log2(GetSize(mrd.data) / mem->width);
+ bool transparent = false;
+ if (is_compat) {
+ transparent = cell->parameters.at(ID::TRANSPARENT).as_bool();
+ mrd.ce_over_srst = false;
+ mrd.arst_value = Const(State::Sx, mem->width << mrd.wide_log2);
+ mrd.srst_value = Const(State::Sx, mem->width << mrd.wide_log2);
+ mrd.init_value = Const(State::Sx, mem->width << mrd.wide_log2);
+ mrd.srst = State::S0;
+ mrd.arst = State::S0;
+ if (!mrd.clk_enable) {
+ // Fix some patterns that we'll allow for backwards compatibility,
+ // but don't want to see moving forwards: async transparent
+ // ports (inherently meaningless) and async ports without
+ // const 1 tied to EN bit (which may mean a latch in the future).
+ transparent = false;
+ if (mrd.en == State::Sx)
+ mrd.en = State::S1;
+ }
+ } else {
+ mrd.ce_over_srst = cell->parameters.at(ID::CE_OVER_SRST).as_bool();
+ mrd.arst_value = cell->parameters.at(ID::ARST_VALUE);
+ mrd.srst_value = cell->parameters.at(ID::SRST_VALUE);
+ mrd.init_value = cell->parameters.at(ID::INIT_VALUE);
+ mrd.arst = cell->getPort(ID::ARST);
+ mrd.srst = cell->getPort(ID::SRST);
+ }
res.rd_ports.push_back(mrd);
+ rd_transparent.push_back(transparent);
}
}
if (index.wr_ports.count(mem->name)) {
std::vector<std::pair<int, MemWr>> ports;
for (auto cell : index.wr_ports.at(mem->name)) {
MemWr mwr;
+ bool is_compat = cell->type == ID($memwr);
mwr.cell = cell;
mwr.attributes = cell->attributes;
mwr.clk_enable = cell->parameters.at(ID::CLK_ENABLE).as_bool();
@@ -287,11 +587,37 @@ namespace {
mwr.en = cell->getPort(ID::EN);
mwr.addr = cell->getPort(ID::ADDR);
mwr.data = cell->getPort(ID::DATA);
- ports.push_back(std::make_pair(cell->parameters.at(ID::PRIORITY).as_int(), mwr));
+ mwr.wide_log2 = ceil_log2(GetSize(mwr.data) / mem->width);
+ ports.push_back(std::make_pair(cell->parameters.at(is_compat ? ID::PRIORITY : ID::PORTID).as_int(), mwr));
}
std::sort(ports.begin(), ports.end(), [](const std::pair<int, MemWr> &a, const std::pair<int, MemWr> &b) { return a.first < b.first; });
- for (auto &it : ports)
+ for (auto &it : ports) {
res.wr_ports.push_back(it.second);
+ wr_portid.push_back(it.first);
+ }
+ for (int i = 0; i < GetSize(res.wr_ports); i++) {
+ auto &port = res.wr_ports[i];
+ bool is_compat = port.cell->type == ID($memwr);
+ if (is_compat) {
+ port.priority_mask.resize(GetSize(res.wr_ports));
+ for (int j = 0; j < i; j++) {
+ auto &oport = res.wr_ports[j];
+ if (port.clk_enable != oport.clk_enable)
+ continue;
+ if (port.clk_enable && port.clk != oport.clk)
+ continue;
+ if (port.clk_enable && port.clk_polarity != oport.clk_polarity)
+ continue;
+ port.priority_mask[j] = true;
+ }
+ } else {
+ Const orig_prio_mask = port.cell->parameters.at(ID::PRIORITY_MASK);
+ for (int orig_portid : wr_portid) {
+ bool has_prio = orig_portid < GetSize(orig_prio_mask) && orig_prio_mask[orig_portid] == State::S1;
+ port.priority_mask.push_back(has_prio);
+ }
+ }
+ }
}
if (index.inits.count(mem->name)) {
std::vector<std::pair<int, MemInit>> inits;
@@ -307,12 +633,50 @@ namespace {
log_error("Non-constant data %s in memory initialization %s.\n", log_signal(data), log_id(cell));
init.addr = addr.as_const();
init.data = data.as_const();
+ if (cell->type == ID($meminit_v2)) {
+ auto en = cell->getPort(ID::EN);
+ if (!en.is_fully_const())
+ log_error("Non-constant enable %s in memory initialization %s.\n", log_signal(en), log_id(cell));
+ init.en = en.as_const();
+ } else {
+ init.en = RTLIL::Const(State::S1, mem->width);
+ }
inits.push_back(std::make_pair(cell->parameters.at(ID::PRIORITY).as_int(), init));
}
std::sort(inits.begin(), inits.end(), [](const std::pair<int, MemInit> &a, const std::pair<int, MemInit> &b) { return a.first < b.first; });
for (auto &it : inits)
res.inits.push_back(it.second);
}
+ for (int i = 0; i < GetSize(res.rd_ports); i++) {
+ auto &port = res.rd_ports[i];
+ bool is_compat = port.cell->type == ID($memrd);
+ if (is_compat) {
+ port.transparency_mask.resize(GetSize(res.wr_ports));
+ port.collision_x_mask.resize(GetSize(res.wr_ports));
+ if (!rd_transparent[i])
+ continue;
+ if (!port.clk_enable)
+ continue;
+ for (int j = 0; j < GetSize(res.wr_ports); j++) {
+ auto &wport = res.wr_ports[j];
+ if (!wport.clk_enable)
+ continue;
+ if (port.clk != wport.clk)
+ continue;
+ if (port.clk_polarity != wport.clk_polarity)
+ continue;
+ port.transparency_mask[j] = true;
+ }
+ } else {
+ Const orig_trans_mask = port.cell->parameters.at(ID::TRANSPARENCY_MASK);
+ Const orig_cx_mask = port.cell->parameters.at(ID::COLLISION_X_MASK);
+ for (int orig_portid : wr_portid) {
+ port.transparency_mask.push_back(orig_portid < GetSize(orig_trans_mask) && orig_trans_mask[orig_portid] == State::S1);
+ port.collision_x_mask.push_back(orig_portid < GetSize(orig_cx_mask) && orig_cx_mask[orig_portid] == State::S1);
+ }
+ }
+ }
+ res.check();
return res;
}
@@ -322,6 +686,7 @@ namespace {
cell->parameters.at(ID::OFFSET).as_int(),
cell->parameters.at(ID::SIZE).as_int()
);
+ bool is_compat = cell->type == ID($mem);
int abits = cell->parameters.at(ID::ABITS).as_int();
res.packed = true;
res.cell = cell;
@@ -343,32 +708,112 @@ namespace {
MemInit minit;
minit.addr = res.start_offset + pos;
minit.data = init.extract(pos * res.width, (epos - pos) * res.width, State::Sx);
+ minit.en = RTLIL::Const(State::S1, res.width);
res.inits.push_back(minit);
pos = epos;
}
}
}
- for (int i = 0; i < cell->parameters.at(ID::RD_PORTS).as_int(); i++) {
+ int n_rd_ports = cell->parameters.at(ID::RD_PORTS).as_int();
+ int n_wr_ports = cell->parameters.at(ID::WR_PORTS).as_int();
+ Const rd_wide_continuation = is_compat ? Const(State::S0, n_rd_ports) : cell->parameters.at(ID::RD_WIDE_CONTINUATION);
+ Const wr_wide_continuation = is_compat ? Const(State::S0, n_wr_ports) : cell->parameters.at(ID::WR_WIDE_CONTINUATION);
+ for (int i = 0, ni; i < n_rd_ports; i = ni) {
+ ni = i + 1;
+ while (ni < n_rd_ports && rd_wide_continuation[ni] == State::S1)
+ ni++;
MemRd mrd;
+ mrd.wide_log2 = ceil_log2(ni - i);
+ log_assert(ni - i == (1 << mrd.wide_log2));
mrd.clk_enable = cell->parameters.at(ID::RD_CLK_ENABLE).extract(i, 1).as_bool();
mrd.clk_polarity = cell->parameters.at(ID::RD_CLK_POLARITY).extract(i, 1).as_bool();
- mrd.transparent = cell->parameters.at(ID::RD_TRANSPARENT).extract(i, 1).as_bool();
mrd.clk = cell->getPort(ID::RD_CLK).extract(i, 1);
mrd.en = cell->getPort(ID::RD_EN).extract(i, 1);
mrd.addr = cell->getPort(ID::RD_ADDR).extract(i * abits, abits);
- mrd.data = cell->getPort(ID::RD_DATA).extract(i * res.width, res.width);
+ mrd.data = cell->getPort(ID::RD_DATA).extract(i * res.width, (ni - i) * res.width);
+ if (is_compat) {
+ mrd.ce_over_srst = false;
+ mrd.arst_value = Const(State::Sx, res.width << mrd.wide_log2);
+ mrd.srst_value = Const(State::Sx, res.width << mrd.wide_log2);
+ mrd.init_value = Const(State::Sx, res.width << mrd.wide_log2);
+ mrd.arst = State::S0;
+ mrd.srst = State::S0;
+ } else {
+ mrd.ce_over_srst = cell->parameters.at(ID::RD_CE_OVER_SRST).extract(i, 1).as_bool();
+ mrd.arst_value = cell->parameters.at(ID::RD_ARST_VALUE).extract(i * res.width, (ni - i) * res.width);
+ mrd.srst_value = cell->parameters.at(ID::RD_SRST_VALUE).extract(i * res.width, (ni - i) * res.width);
+ mrd.init_value = cell->parameters.at(ID::RD_INIT_VALUE).extract(i * res.width, (ni - i) * res.width);
+ mrd.arst = cell->getPort(ID::RD_ARST).extract(i, 1);
+ mrd.srst = cell->getPort(ID::RD_SRST).extract(i, 1);
+ }
+ if (!is_compat) {
+ Const transparency_mask = cell->parameters.at(ID::RD_TRANSPARENCY_MASK).extract(i * n_wr_ports, n_wr_ports);
+ Const collision_x_mask = cell->parameters.at(ID::RD_COLLISION_X_MASK).extract(i * n_wr_ports, n_wr_ports);
+ for (int j = 0; j < n_wr_ports; j++)
+ if (wr_wide_continuation[j] != State::S1) {
+ mrd.transparency_mask.push_back(transparency_mask[j] == State::S1);
+ mrd.collision_x_mask.push_back(collision_x_mask[j] == State::S1);
+ }
+ }
res.rd_ports.push_back(mrd);
}
- for (int i = 0; i < cell->parameters.at(ID::WR_PORTS).as_int(); i++) {
+ for (int i = 0, ni; i < n_wr_ports; i = ni) {
+ ni = i + 1;
+ while (ni < n_wr_ports && wr_wide_continuation[ni] == State::S1)
+ ni++;
MemWr mwr;
+ mwr.wide_log2 = ceil_log2(ni - i);
+ log_assert(ni - i == (1 << mwr.wide_log2));
mwr.clk_enable = cell->parameters.at(ID::WR_CLK_ENABLE).extract(i, 1).as_bool();
mwr.clk_polarity = cell->parameters.at(ID::WR_CLK_POLARITY).extract(i, 1).as_bool();
mwr.clk = cell->getPort(ID::WR_CLK).extract(i, 1);
- mwr.en = cell->getPort(ID::WR_EN).extract(i * res.width, res.width);
+ mwr.en = cell->getPort(ID::WR_EN).extract(i * res.width, (ni - i) * res.width);
mwr.addr = cell->getPort(ID::WR_ADDR).extract(i * abits, abits);
- mwr.data = cell->getPort(ID::WR_DATA).extract(i * res.width, res.width);
+ mwr.data = cell->getPort(ID::WR_DATA).extract(i * res.width, (ni - i) * res.width);
+ if (!is_compat) {
+ Const priority_mask = cell->parameters.at(ID::WR_PRIORITY_MASK).extract(i * n_wr_ports, n_wr_ports);
+ for (int j = 0; j < n_wr_ports; j++)
+ if (wr_wide_continuation[j] != State::S1)
+ mwr.priority_mask.push_back(priority_mask[j] == State::S1);
+ }
res.wr_ports.push_back(mwr);
}
+ if (is_compat) {
+ for (int i = 0; i < GetSize(res.wr_ports); i++) {
+ auto &port = res.wr_ports[i];
+ port.priority_mask.resize(GetSize(res.wr_ports));
+ for (int j = 0; j < i; j++) {
+ auto &oport = res.wr_ports[j];
+ if (port.clk_enable != oport.clk_enable)
+ continue;
+ if (port.clk_enable && port.clk != oport.clk)
+ continue;
+ if (port.clk_enable && port.clk_polarity != oport.clk_polarity)
+ continue;
+ port.priority_mask[j] = true;
+ }
+ }
+ for (int i = 0; i < GetSize(res.rd_ports); i++) {
+ auto &port = res.rd_ports[i];
+ port.transparency_mask.resize(GetSize(res.wr_ports));
+ port.collision_x_mask.resize(GetSize(res.wr_ports));
+ if (!cell->parameters.at(ID::RD_TRANSPARENT).extract(i, 1).as_bool())
+ continue;
+ if (!port.clk_enable)
+ continue;
+ for (int j = 0; j < GetSize(res.wr_ports); j++) {
+ auto &wport = res.wr_ports[j];
+ if (!wport.clk_enable)
+ continue;
+ if (port.clk != wport.clk)
+ continue;
+ if (port.clk_polarity != wport.clk_polarity)
+ continue;
+ port.transparency_mask[j] = true;
+ }
+ }
+ }
+ res.check();
return res;
}
@@ -381,7 +826,7 @@ std::vector<Mem> Mem::get_all_memories(Module *module) {
res.push_back(mem_from_memory(module, it.second, index));
}
for (auto cell: module->cells()) {
- if (cell->type == ID($mem))
+ if (cell->type.in(ID($mem), ID($mem_v2)))
res.push_back(mem_from_cell(cell));
}
return res;
@@ -395,13 +840,13 @@ std::vector<Mem> Mem::get_selected_memories(Module *module) {
res.push_back(mem_from_memory(module, it.second, index));
}
for (auto cell: module->selected_cells()) {
- if (cell->type == ID($mem))
+ if (cell->type.in(ID($mem), ID($mem_v2)))
res.push_back(mem_from_cell(cell));
}
return res;
}
-Cell *Mem::extract_rdff(int idx) {
+Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
MemRd &port = rd_ports[idx];
if (!port.clk_enable)
@@ -409,28 +854,813 @@ Cell *Mem::extract_rdff(int idx) {
Cell *c;
- if (port.transparent)
+ // There are two ways to handle rdff extraction when transparency is involved:
+ //
+ // - if all of the following conditions are true, put the FF on address input:
+ //
+ // - the port has no clock enable, no reset, and no initial value
+ // - the port is transparent wrt all write ports (implying they also share
+ // the clock domain)
+ //
+ // - otherwise, put the FF on the data output, and make bypass paths for
+ // all write ports wrt which this port is transparent
+ bool trans_use_addr = true;
+ for (int i = 0; i < GetSize(wr_ports); i++)
+ if (!port.transparency_mask[i] && !wr_ports[i].removed)
+ trans_use_addr = false;
+
+ // If there are no write ports at all, we could possibly use either way; do data
+ // FF in this case.
+ if (GetSize(wr_ports) == 0)
+ trans_use_addr = false;
+
+ if (port.en != State::S1 || port.srst != State::S0 || port.arst != State::S0 || !port.init_value.is_fully_undef())
+ trans_use_addr = false;
+
+ if (trans_use_addr)
{
- SigSpec sig_q = module->addWire(stringf("%s$rdreg[%d]$q", memid.c_str(), idx), GetSize(port.addr));
- SigSpec sig_d = port.addr;
- port.addr = sig_q;
- c = module->addDffe(stringf("%s$rdreg[%d]", memid.c_str(), idx), port.clk, port.en, sig_d, sig_q, port.clk_polarity, true);
+ // Do not put a register in front of constant address bits — this is both
+ // unnecessary and will break wide ports.
+ int width = 0;
+ for (int i = 0; i < GetSize(port.addr); i++)
+ if (port.addr[i].wire)
+ width++;
+
+ if (width)
+ {
+ SigSpec sig_q = module->addWire(stringf("$%s$rdreg[%d]$q", memid.c_str(), idx), width);
+ SigSpec sig_d;
+
+ int pos = 0;
+ for (int i = 0; i < GetSize(port.addr); i++)
+ if (port.addr[i].wire) {
+ sig_d.append(port.addr[i]);
+ port.addr[i] = sig_q[pos++];
+ }
+
+ c = module->addDff(stringf("$%s$rdreg[%d]", memid.c_str(), idx), port.clk, sig_d, sig_q, port.clk_polarity);
+ } else {
+ c = nullptr;
+ }
}
else
{
- SigSpec sig_d = module->addWire(stringf("%s$rdreg[%d]$d", memid.c_str(), idx), width);
- SigSpec sig_q = port.data;
- port.data = sig_d;
- c = module->addDffe(stringf("%s$rdreg[%d]", memid.c_str(), idx), port.clk, port.en, sig_d, sig_q, port.clk_polarity, true);
+ log_assert(port.arst == State::S0 || port.srst == State::S0);
+
+ SigSpec async_d = module->addWire(stringf("$%s$rdreg[%d]$d", memid.c_str(), idx), GetSize(port.data));
+ SigSpec sig_d = async_d;
+
+ for (int i = 0; i < GetSize(wr_ports); i++) {
+ auto &wport = wr_ports[i];
+ if (wport.removed)
+ continue;
+ if (port.transparency_mask[i] || port.collision_x_mask[i]) {
+ log_assert(wport.clk_enable);
+ log_assert(wport.clk == port.clk);
+ log_assert(wport.clk_enable == port.clk_enable);
+ int min_wide_log2 = std::min(port.wide_log2, wport.wide_log2);
+ int max_wide_log2 = std::max(port.wide_log2, wport.wide_log2);
+ bool wide_write = wport.wide_log2 > port.wide_log2;
+ for (int sub = 0; sub < (1 << max_wide_log2); sub += (1 << min_wide_log2)) {
+ SigSpec raddr = port.addr;
+ SigSpec waddr = wport.addr;
+ if (wide_write)
+ waddr = wport.sub_addr(sub);
+ else
+ raddr = port.sub_addr(sub);
+ SigSpec addr_eq;
+ if (raddr != waddr)
+ addr_eq = module->Eq(stringf("$%s$rdtransen[%d][%d][%d]$d", memid.c_str(), idx, i, sub), raddr, waddr);
+ int pos = 0;
+ int ewidth = width << min_wide_log2;
+ int wsub = wide_write ? sub : 0;
+ int rsub = wide_write ? 0 : sub;
+ while (pos < ewidth) {
+ int epos = pos;
+ while (epos < ewidth && wport.en[epos + wsub * width] == wport.en[pos + wsub * width])
+ epos++;
+ SigSpec cur = sig_d.extract(pos + rsub * width, epos-pos);
+ SigSpec other = port.transparency_mask[i] ? wport.data.extract(pos + wsub * width, epos-pos) : Const(State::Sx, epos-pos);
+ SigSpec cond;
+ if (raddr != waddr)
+ cond = module->And(stringf("$%s$rdtransgate[%d][%d][%d][%d]$d", memid.c_str(), idx, i, sub, pos), wport.en[pos + wsub * width], addr_eq);
+ else
+ cond = wport.en[pos + wsub * width];
+ SigSpec merged = module->Mux(stringf("$%s$rdtransmux[%d][%d][%d][%d]$d", memid.c_str(), idx, i, sub, pos), cur, other, cond);
+ sig_d.replace(pos + rsub * width, merged);
+ pos = epos;
+ }
+ }
+ }
+ }
+
+ IdString name = stringf("$%s$rdreg[%d]", memid.c_str(), idx);
+ FfData ff(module, initvals, name);
+ ff.width = GetSize(port.data);
+ ff.has_clk = true;
+ ff.sig_clk = port.clk;
+ ff.pol_clk = port.clk_polarity;
+ if (port.en != State::S1) {
+ ff.has_ce = true;
+ ff.pol_ce = true;
+ ff.sig_ce = port.en;
+ }
+ if (port.arst != State::S0) {
+ ff.has_arst = true;
+ ff.pol_arst = true;
+ ff.sig_arst = port.arst;
+ ff.val_arst = port.arst_value;
+ }
+ if (port.srst != State::S0) {
+ ff.has_srst = true;
+ ff.pol_srst = true;
+ ff.sig_srst = port.srst;
+ ff.val_srst = port.srst_value;
+ ff.ce_over_srst = ff.has_ce && port.ce_over_srst;
+ }
+ ff.sig_d = sig_d;
+ ff.sig_q = port.data;
+ ff.val_init = port.init_value;
+ port.data = async_d;
+ c = ff.emit();
}
- log("Extracted %s FF from read port %d of %s.%s: %s\n", port.transparent ? "addr" : "data",
+ if (c)
+ log("Extracted %s FF from read port %d of %s.%s: %s\n", trans_use_addr ? "addr" : "data",
idx, log_id(module), log_id(memid), log_id(c));
port.en = State::S1;
port.clk = State::S0;
+ port.arst = State::S0;
+ port.srst = State::S0;
port.clk_enable = false;
port.clk_polarity = true;
+ port.ce_over_srst = false;
+ port.arst_value = Const(State::Sx, GetSize(port.data));
+ port.srst_value = Const(State::Sx, GetSize(port.data));
+ port.init_value = Const(State::Sx, GetSize(port.data));
+
+ for (int i = 0; i < GetSize(wr_ports); i++) {
+ port.transparency_mask[i] = false;
+ port.collision_x_mask[i] = false;
+ }
return c;
}
+
+void Mem::narrow() {
+ // NOTE: several passes depend on this function not modifying
+ // the design at all until (and unless) emit() is called.
+ // Be careful to preserve this.
+ std::vector<MemRd> new_rd_ports;
+ std::vector<MemWr> new_wr_ports;
+ std::vector<std::pair<int, int>> new_rd_map;
+ std::vector<std::pair<int, int>> new_wr_map;
+ for (int i = 0; i < GetSize(rd_ports); i++) {
+ auto &port = rd_ports[i];
+ for (int sub = 0; sub < (1 << port.wide_log2); sub++) {
+ new_rd_map.push_back(std::make_pair(i, sub));
+ }
+ }
+ for (int i = 0; i < GetSize(wr_ports); i++) {
+ auto &port = wr_ports[i];
+ for (int sub = 0; sub < (1 << port.wide_log2); sub++) {
+ new_wr_map.push_back(std::make_pair(i, sub));
+ }
+ }
+ for (auto &it : new_rd_map) {
+ MemRd &orig = rd_ports[it.first];
+ MemRd port = orig;
+ if (it.second != 0)
+ port.cell = nullptr;
+ if (port.wide_log2) {
+ port.data = port.data.extract(it.second * width, width);
+ port.init_value = port.init_value.extract(it.second * width, width);
+ port.arst_value = port.arst_value.extract(it.second * width, width);
+ port.srst_value = port.srst_value.extract(it.second * width, width);
+ port.addr = port.sub_addr(it.second);
+ port.wide_log2 = 0;
+ }
+ port.transparency_mask.clear();
+ port.collision_x_mask.clear();
+ for (auto &it2 : new_wr_map)
+ port.transparency_mask.push_back(orig.transparency_mask[it2.first]);
+ for (auto &it2 : new_wr_map)
+ port.collision_x_mask.push_back(orig.collision_x_mask[it2.first]);
+ new_rd_ports.push_back(port);
+ }
+ for (auto &it : new_wr_map) {
+ MemWr &orig = wr_ports[it.first];
+ MemWr port = orig;
+ if (it.second != 0)
+ port.cell = nullptr;
+ if (port.wide_log2) {
+ port.data = port.data.extract(it.second * width, width);
+ port.en = port.en.extract(it.second * width, width);
+ port.addr = port.sub_addr(it.second);
+ port.wide_log2 = 0;
+ }
+ port.priority_mask.clear();
+ for (auto &it2 : new_wr_map)
+ port.priority_mask.push_back(orig.priority_mask[it2.first]);
+ new_wr_ports.push_back(port);
+ }
+ std::swap(rd_ports, new_rd_ports);
+ std::swap(wr_ports, new_wr_ports);
+}
+
+void Mem::emulate_priority(int idx1, int idx2, FfInitVals *initvals)
+{
+ auto &port1 = wr_ports[idx1];
+ auto &port2 = wr_ports[idx2];
+ if (!port2.priority_mask[idx1])
+ return;
+ for (int i = 0; i < GetSize(rd_ports); i++) {
+ auto &rport = rd_ports[i];
+ if (rport.removed)
+ continue;
+ if (rport.transparency_mask[idx1] && !(rport.transparency_mask[idx2] || rport.collision_x_mask[idx2]))
+ emulate_transparency(idx1, i, initvals);
+ }
+ int min_wide_log2 = std::min(port1.wide_log2, port2.wide_log2);
+ int max_wide_log2 = std::max(port1.wide_log2, port2.wide_log2);
+ bool wide1 = port1.wide_log2 > port2.wide_log2;
+ for (int sub = 0; sub < (1 << max_wide_log2); sub += (1 << min_wide_log2)) {
+ SigSpec addr1 = port1.addr;
+ SigSpec addr2 = port2.addr;
+ if (wide1)
+ addr1 = port1.sub_addr(sub);
+ else
+ addr2 = port2.sub_addr(sub);
+ SigSpec addr_eq = module->Eq(NEW_ID, addr1, addr2);
+ int ewidth = width << min_wide_log2;
+ int sub1 = wide1 ? sub : 0;
+ int sub2 = wide1 ? 0 : sub;
+ dict<std::pair<SigBit, SigBit>, SigBit> cache;
+ for (int pos = 0; pos < ewidth; pos++) {
+ SigBit &en1 = port1.en[pos + sub1 * width];
+ SigBit &en2 = port2.en[pos + sub2 * width];
+ std::pair<SigBit, SigBit> key(en1, en2);
+ if (cache.count(key)) {
+ en1 = cache[key];
+ } else {
+ SigBit active2 = module->And(NEW_ID, addr_eq, en2);
+ SigBit nactive2 = module->Not(NEW_ID, active2);
+ en1 = cache[key] = module->And(NEW_ID, en1, nactive2);
+ }
+ }
+ }
+ port2.priority_mask[idx1] = false;
+}
+
+void Mem::emulate_transparency(int widx, int ridx, FfInitVals *initvals) {
+ auto &wport = wr_ports[widx];
+ auto &rport = rd_ports[ridx];
+ log_assert(rport.transparency_mask[widx]);
+ // If other write ports have priority over this one, emulate their transparency too.
+ for (int i = GetSize(wr_ports) - 1; i > widx; i--) {
+ if (wr_ports[i].removed)
+ continue;
+ if (rport.transparency_mask[i] && wr_ports[i].priority_mask[widx])
+ emulate_transparency(i, ridx, initvals);
+ }
+ int min_wide_log2 = std::min(rport.wide_log2, wport.wide_log2);
+ int max_wide_log2 = std::max(rport.wide_log2, wport.wide_log2);
+ bool wide_write = wport.wide_log2 > rport.wide_log2;
+ // The write data FF doesn't need full reset/init behavior, as it'll be masked by
+ // the mux whenever this would be relevant. It does, however, need to have the same
+ // clock enable signal as the read port.
+ SigSpec wdata_q = module->addWire(NEW_ID, GetSize(wport.data));
+ module->addDffe(NEW_ID, rport.clk, rport.en, wport.data, wdata_q, rport.clk_polarity, true);
+ for (int sub = 0; sub < (1 << max_wide_log2); sub += (1 << min_wide_log2)) {
+ SigSpec raddr = rport.addr;
+ SigSpec waddr = wport.addr;
+ for (int j = min_wide_log2; j < max_wide_log2; j++)
+ if (wide_write)
+ waddr = wport.sub_addr(sub);
+ else
+ raddr = rport.sub_addr(sub);
+ SigSpec addr_eq;
+ if (raddr != waddr)
+ addr_eq = module->Eq(NEW_ID, raddr, waddr);
+ int pos = 0;
+ int ewidth = width << min_wide_log2;
+ int wsub = wide_write ? sub : 0;
+ int rsub = wide_write ? 0 : sub;
+ SigSpec rdata_a = module->addWire(NEW_ID, ewidth);
+ while (pos < ewidth) {
+ int epos = pos;
+ while (epos < ewidth && wport.en[epos + wsub * width] == wport.en[pos + wsub * width])
+ epos++;
+ SigSpec cond;
+ if (raddr != waddr)
+ cond = module->And(NEW_ID, wport.en[pos + wsub * width], addr_eq);
+ else
+ cond = wport.en[pos + wsub * width];
+ SigSpec cond_q = module->addWire(NEW_ID);
+ // The FF for storing the bypass enable signal must be carefully
+ // constructed to preserve the overall init/reset/enable behavior
+ // of the whole port.
+ FfData ff(module, initvals, NEW_ID);
+ ff.width = 1;
+ ff.sig_q = cond_q;
+ ff.sig_d = cond;
+ ff.has_clk = true;
+ ff.sig_clk = rport.clk;
+ ff.pol_clk = rport.clk_polarity;
+ if (rport.en != State::S1) {
+ ff.has_ce = true;
+ ff.sig_ce = rport.en;
+ ff.pol_ce = true;
+ }
+ if (rport.arst != State::S0) {
+ ff.has_arst = true;
+ ff.sig_arst = rport.arst;
+ ff.pol_arst = true;
+ ff.val_arst = State::S0;
+ }
+ if (rport.srst != State::S0) {
+ ff.has_srst = true;
+ ff.sig_srst = rport.srst;
+ ff.pol_srst = true;
+ ff.val_srst = State::S0;
+ ff.ce_over_srst = rport.ce_over_srst;
+ }
+ if (!rport.init_value.is_fully_undef())
+ ff.val_init = State::S0;
+ else
+ ff.val_init = State::Sx;
+ ff.emit();
+ // And the final bypass mux.
+ SigSpec cur = rdata_a.extract(pos, epos-pos);
+ SigSpec other = wdata_q.extract(pos + wsub * width, epos-pos);
+ SigSpec dest = rport.data.extract(pos + rsub * width, epos-pos);
+ module->addMux(NEW_ID, cur, other, cond_q, dest);
+ pos = epos;
+ }
+ rport.data.replace(rsub * width, rdata_a);
+ }
+ rport.transparency_mask[widx] = false;
+ rport.collision_x_mask[widx] = true;
+}
+
+void Mem::prepare_wr_merge(int idx1, int idx2, FfInitVals *initvals) {
+ log_assert(idx1 < idx2);
+ auto &port1 = wr_ports[idx1];
+ auto &port2 = wr_ports[idx2];
+ // If port 2 has priority over a port before port 1, make port 1 have priority too.
+ for (int i = 0; i < idx1; i++)
+ if (port2.priority_mask[i])
+ port1.priority_mask[i] = true;
+ // If port 2 has priority over a port after port 1, emulate it.
+ for (int i = idx1 + 1; i < idx2; i++)
+ if (port2.priority_mask[i] && !wr_ports[i].removed)
+ emulate_priority(i, idx2, initvals);
+ // If some port had priority over port 2, make it have priority over the merged port too.
+ for (int i = idx2 + 1; i < GetSize(wr_ports); i++) {
+ auto &oport = wr_ports[i];
+ if (oport.priority_mask[idx2])
+ oport.priority_mask[idx1] = true;
+ }
+ // Make sure all read ports have identical collision/transparency behavior wrt both
+ // ports.
+ for (int i = 0; i < GetSize(rd_ports); i++) {
+ auto &rport = rd_ports[i];
+ if (rport.removed)
+ continue;
+ // If collision already undefined with both ports, it's fine.
+ if (rport.collision_x_mask[idx1] && rport.collision_x_mask[idx2])
+ continue;
+ // If one port has undefined collision, change it to the behavior
+ // of the other port.
+ if (rport.collision_x_mask[idx1]) {
+ rport.collision_x_mask[idx1] = false;
+ rport.transparency_mask[idx1] = rport.transparency_mask[idx2];
+ continue;
+ }
+ if (rport.collision_x_mask[idx2]) {
+ rport.collision_x_mask[idx2] = false;
+ rport.transparency_mask[idx2] = rport.transparency_mask[idx1];
+ continue;
+ }
+ // If transparent with both ports, also fine.
+ if (rport.transparency_mask[idx1] && rport.transparency_mask[idx2])
+ continue;
+ // If transparent with only one, emulate it, and remove the collision-X
+ // flag that emulate_transparency will set (to align with the other port).
+ if (rport.transparency_mask[idx1]) {
+ emulate_transparency(i, idx1, initvals);
+ rport.collision_x_mask[idx1] = false;
+ continue;
+ }
+ if (rport.transparency_mask[idx2]) {
+ emulate_transparency(i, idx2, initvals);
+ rport.collision_x_mask[idx2] = false;
+ continue;
+ }
+ // If we got here, it's transparent with neither port, which is fine.
+ }
+}
+
+void Mem::prepare_rd_merge(int idx1, int idx2, FfInitVals *initvals) {
+ auto &port1 = rd_ports[idx1];
+ auto &port2 = rd_ports[idx2];
+ // Note that going through write ports in order is important, since
+ // emulating transparency of a write port can change transparency
+ // mask for higher-numbered ports (due to transitive transparency
+ // emulation needed because of write port priority).
+ for (int i = 0; i < GetSize(wr_ports); i++) {
+ if (wr_ports[i].removed)
+ continue;
+ // Both ports undefined, OK.
+ if (port1.collision_x_mask[i] && port2.collision_x_mask[i])
+ continue;
+ // Only one port undefined — change its behavior
+ // to align with the other port.
+ if (port1.collision_x_mask[i]) {
+ port1.collision_x_mask[i] = false;
+ port1.transparency_mask[i] = port2.transparency_mask[i];
+ continue;
+ }
+ if (port2.collision_x_mask[i]) {
+ port2.collision_x_mask[i] = false;
+ port2.transparency_mask[i] = port1.transparency_mask[i];
+ continue;
+ }
+ // Both ports transparent, OK.
+ if (port1.transparency_mask[i] && port2.transparency_mask[i])
+ continue;
+ // Only one port transparent — emulate transparency
+ // on the other.
+ if (port1.transparency_mask[i]) {
+ emulate_transparency(i, idx1, initvals);
+ port1.collision_x_mask[i] = false;
+ continue;
+ }
+ if (port2.transparency_mask[i]) {
+ emulate_transparency(i, idx2, initvals);
+ port2.collision_x_mask[i] = false;
+ continue;
+ }
+ // No ports transparent, OK.
+ }
+
+}
+
+void Mem::widen_prep(int wide_log2) {
+ // Make sure start_offset and size are aligned to the port width,
+ // adjust if necessary.
+ int mask = ((1 << wide_log2) - 1);
+ int delta = start_offset & mask;
+ start_offset -= delta;
+ size += delta;
+ if (size & mask) {
+ size |= mask;
+ size++;
+ }
+}
+
+void Mem::widen_wr_port(int idx, int wide_log2) {
+ widen_prep(wide_log2);
+ auto &port = wr_ports[idx];
+ log_assert(port.wide_log2 <= wide_log2);
+ if (port.wide_log2 < wide_log2) {
+ SigSpec new_data, new_en;
+ SigSpec addr_lo = port.addr.extract(0, wide_log2);
+ for (int sub = 0; sub < (1 << wide_log2); sub += (1 << port.wide_log2))
+ {
+ Const cur_addr_lo(sub, wide_log2);
+ if (addr_lo == cur_addr_lo) {
+ // Always writes to this subword.
+ new_data.append(port.data);
+ new_en.append(port.en);
+ } else if (addr_lo.is_fully_const()) {
+ // Never writes to this subword.
+ new_data.append(Const(State::Sx, GetSize(port.data)));
+ new_en.append(Const(State::S0, GetSize(port.data)));
+ } else {
+ // May or may not write to this subword.
+ new_data.append(port.data);
+ SigSpec addr_eq = module->Eq(NEW_ID, addr_lo, cur_addr_lo);
+ SigSpec en = module->Mux(NEW_ID, Const(State::S0, GetSize(port.data)), port.en, addr_eq);
+ new_en.append(en);
+ }
+ }
+ port.addr.replace(port.wide_log2, Const(State::S0, wide_log2 - port.wide_log2));
+ port.data = new_data;
+ port.en = new_en;
+ port.wide_log2 = wide_log2;
+ }
+}
+
+void Mem::emulate_rden(int idx, FfInitVals *initvals) {
+ auto &port = rd_ports[idx];
+ log_assert(port.clk_enable);
+ emulate_rd_ce_over_srst(idx);
+ Wire *new_data = module->addWire(NEW_ID, GetSize(port.data));
+ Wire *prev_data = module->addWire(NEW_ID, GetSize(port.data));
+ Wire *sel = module->addWire(NEW_ID);
+ FfData ff_sel(module, initvals, NEW_ID);
+ FfData ff_data(module, initvals, NEW_ID);
+ ff_sel.width = 1;
+ ff_sel.has_clk = true;
+ ff_sel.sig_clk = port.clk;
+ ff_sel.pol_clk = port.clk_polarity;
+ ff_sel.sig_d = port.en;
+ ff_sel.sig_q = sel;
+ ff_data.width = GetSize(port.data);
+ ff_data.has_clk = true;
+ ff_data.sig_clk = port.clk;
+ ff_data.pol_clk = port.clk_polarity;
+ ff_data.sig_d = port.data;
+ ff_data.sig_q = prev_data;
+ if (!port.init_value.is_fully_undef()) {
+ ff_sel.val_init = State::S0;
+ ff_data.val_init = port.init_value;
+ port.init_value = Const(State::Sx, GetSize(port.data));
+ } else {
+ ff_sel.val_init = State::Sx;
+ ff_data.val_init = Const(State::Sx, GetSize(port.data));
+ }
+ if (port.arst != State::S0) {
+ ff_sel.has_arst = true;
+ ff_sel.val_arst = State::S0;
+ ff_sel.sig_arst = port.arst;
+ ff_sel.pol_arst = true;
+ ff_data.has_arst = true;
+ ff_data.val_arst = port.arst_value;
+ ff_data.sig_arst = port.arst;
+ ff_data.pol_arst = true;
+ port.arst = State::S0;
+ }
+ if (port.srst != State::S0) {
+ log_assert(!port.ce_over_srst);
+ ff_sel.has_srst = true;
+ ff_sel.val_srst = State::S0;
+ ff_sel.sig_srst = port.srst;
+ ff_sel.pol_srst = true;
+ ff_sel.ce_over_srst = false;
+ ff_data.has_srst = true;
+ ff_data.val_srst = port.srst_value;
+ ff_data.sig_srst = port.srst;
+ ff_data.pol_srst = true;
+ ff_data.ce_over_srst = false;
+ port.srst = State::S0;
+ }
+ ff_sel.emit();
+ ff_data.emit();
+ module->addMux(NEW_ID, prev_data, new_data, sel, port.data);
+ port.data = new_data;
+ port.en = State::S1;
+}
+
+void Mem::emulate_reset(int idx, bool emu_init, bool emu_arst, bool emu_srst, FfInitVals *initvals) {
+ auto &port = rd_ports[idx];
+ if (emu_init && !port.init_value.is_fully_undef()) {
+ Wire *sel = module->addWire(NEW_ID);
+ FfData ff_sel(module, initvals, NEW_ID);
+ Wire *new_data = module->addWire(NEW_ID, GetSize(port.data));
+ ff_sel.width = 1;
+ ff_sel.has_clk = true;
+ ff_sel.sig_clk = port.clk;
+ ff_sel.pol_clk = port.clk_polarity;
+ ff_sel.sig_d = State::S1;
+ ff_sel.sig_q = sel;
+ ff_sel.val_init = State::S0;
+ if (port.en != State::S1) {
+ ff_sel.has_ce = true;
+ ff_sel.sig_ce = port.en;
+ ff_sel.pol_ce = true;
+ ff_sel.ce_over_srst = port.ce_over_srst;
+ }
+ if (port.arst != State::S0) {
+ ff_sel.has_arst = true;
+ ff_sel.sig_arst = port.arst;
+ ff_sel.pol_arst = true;
+ if (emu_arst && port.arst_value == port.init_value) {
+ // If we're going to emulate async reset anyway, and the reset
+ // value is the same as init value, reuse the same mux.
+ ff_sel.val_arst = State::S0;
+ port.arst = State::S0;
+ } else {
+ ff_sel.val_arst = State::S1;
+ }
+ }
+ if (port.srst != State::S0) {
+ ff_sel.has_srst = true;
+ ff_sel.sig_srst = port.srst;
+ ff_sel.pol_srst = true;
+ if (emu_srst && port.srst_value == port.init_value) {
+ ff_sel.val_srst = State::S0;
+ port.srst = State::S0;
+ } else {
+ ff_sel.val_srst = State::S1;
+ }
+ }
+ ff_sel.emit();
+ module->addMux(NEW_ID, port.init_value, new_data, sel, port.data);
+ port.data = new_data;
+ port.init_value = Const(State::Sx, GetSize(port.data));
+ }
+ if (emu_arst && port.arst != State::S0) {
+ Wire *sel = module->addWire(NEW_ID);
+ FfData ff_sel(module, initvals, NEW_ID);
+ Wire *new_data = module->addWire(NEW_ID, GetSize(port.data));
+ ff_sel.width = 1;
+ ff_sel.has_clk = true;
+ ff_sel.sig_clk = port.clk;
+ ff_sel.pol_clk = port.clk_polarity;
+ ff_sel.sig_d = State::S1;
+ ff_sel.sig_q = sel;
+ if (port.init_value.is_fully_undef())
+ ff_sel.val_init = State::Sx;
+ else
+ ff_sel.val_init = State::S1;
+ if (port.en != State::S1) {
+ ff_sel.has_ce = true;
+ ff_sel.sig_ce = port.en;
+ ff_sel.pol_ce = true;
+ ff_sel.ce_over_srst = port.ce_over_srst;
+ }
+ ff_sel.has_arst = true;
+ ff_sel.sig_arst = port.arst;
+ ff_sel.pol_arst = true;
+ ff_sel.val_arst = State::S0;
+ if (port.srst != State::S0) {
+ ff_sel.has_srst = true;
+ ff_sel.sig_srst = port.srst;
+ ff_sel.pol_srst = true;
+ if (emu_srst && port.srst_value == port.arst_value) {
+ ff_sel.val_srst = State::S0;
+ port.srst = State::S0;
+ } else {
+ ff_sel.val_srst = State::S1;
+ }
+ }
+ ff_sel.emit();
+ module->addMux(NEW_ID, port.arst_value, new_data, sel, port.data);
+ port.data = new_data;
+ port.arst = State::S0;
+ }
+ if (emu_srst && port.srst != State::S0) {
+ Wire *sel = module->addWire(NEW_ID);
+ FfData ff_sel(module, initvals, NEW_ID);
+ Wire *new_data = module->addWire(NEW_ID, GetSize(port.data));
+ ff_sel.width = 1;
+ ff_sel.has_clk = true;
+ ff_sel.sig_clk = port.clk;
+ ff_sel.pol_clk = port.clk_polarity;
+ ff_sel.sig_d = State::S1;
+ ff_sel.sig_q = sel;
+ if (port.init_value.is_fully_undef())
+ ff_sel.val_init = State::Sx;
+ else
+ ff_sel.val_init = State::S1;
+ if (port.en != State::S1) {
+ ff_sel.has_ce = true;
+ ff_sel.sig_ce = port.en;
+ ff_sel.pol_ce = true;
+ ff_sel.ce_over_srst = port.ce_over_srst;
+ }
+ ff_sel.has_srst = true;
+ ff_sel.sig_srst = port.srst;
+ ff_sel.pol_srst = true;
+ ff_sel.val_srst = State::S0;
+ if (port.arst != State::S0) {
+ ff_sel.has_arst = true;
+ ff_sel.sig_arst = port.arst;
+ ff_sel.pol_arst = true;
+ ff_sel.val_arst = State::S1;
+ }
+ ff_sel.emit();
+ module->addMux(NEW_ID, port.srst_value, new_data, sel, port.data);
+ port.data = new_data;
+ port.srst = State::S0;
+ }
+}
+
+void Mem::emulate_rd_ce_over_srst(int idx) {
+ auto &port = rd_ports[idx];
+ log_assert(port.clk_enable);
+ if (port.en == State::S1 || port.srst == State::S0 || !port.ce_over_srst) {
+ port.ce_over_srst = false;
+ return;
+ }
+ port.ce_over_srst = false;
+ port.srst = module->And(NEW_ID, port.en, port.srst);
+}
+
+void Mem::emulate_rd_srst_over_ce(int idx) {
+ auto &port = rd_ports[idx];
+ log_assert(port.clk_enable);
+ if (port.en == State::S1 || port.srst == State::S0 || port.ce_over_srst) {
+ port.ce_over_srst = true;
+ return;
+ }
+ port.ce_over_srst = true;
+ port.en = module->Or(NEW_ID, port.en, port.srst);
+}
+
+bool Mem::emulate_read_first_ok() {
+ if (wr_ports.empty())
+ return false;
+ SigSpec clk = wr_ports[0].clk;
+ bool clk_polarity = wr_ports[0].clk_polarity;
+ for (auto &port: wr_ports) {
+ if (!port.clk_enable)
+ return false;
+ if (port.clk != clk)
+ return false;
+ if (port.clk_polarity != clk_polarity)
+ return false;
+ }
+ bool found_read_first = false;
+ for (auto &port: rd_ports) {
+ if (!port.clk_enable)
+ return false;
+ if (port.clk != clk)
+ return false;
+ if (port.clk_polarity != clk_polarity)
+ return false;
+ // No point doing this operation if there is no read-first relationship
+ // in the first place.
+ for (int j = 0; j < GetSize(wr_ports); j++)
+ if (!port.transparency_mask[j] && !port.collision_x_mask[j])
+ found_read_first = true;
+ }
+ return found_read_first;
+}
+
+void Mem::emulate_read_first(FfInitVals *initvals) {
+ log_assert(emulate_read_first_ok());
+ for (int i = 0; i < GetSize(rd_ports); i++)
+ for (int j = 0; j < GetSize(wr_ports); j++)
+ if (rd_ports[i].transparency_mask[j])
+ emulate_transparency(j, i, initvals);
+ for (int i = 0; i < GetSize(rd_ports); i++)
+ for (int j = 0; j < GetSize(wr_ports); j++) {
+ log_assert(!rd_ports[i].transparency_mask[j]);
+ rd_ports[i].collision_x_mask[j] = false;
+ rd_ports[i].transparency_mask[j] = true;
+ }
+ for (auto &port: wr_ports) {
+ Wire *new_data = module->addWire(NEW_ID, GetSize(port.data));
+ Wire *new_addr = module->addWire(NEW_ID, GetSize(port.addr));
+ auto compressed = port.compress_en();
+ Wire *new_en = module->addWire(NEW_ID, GetSize(compressed.first));
+ FfData ff_data(module, initvals, NEW_ID);
+ FfData ff_addr(module, initvals, NEW_ID);
+ FfData ff_en(module, initvals, NEW_ID);
+ ff_data.width = GetSize(port.data);
+ ff_data.has_clk = true;
+ ff_data.sig_clk = port.clk;
+ ff_data.pol_clk = port.clk_polarity;
+ ff_data.sig_d = port.data;
+ ff_data.sig_q = new_data;;
+ ff_data.val_init = Const(State::Sx, ff_data.width);
+ ff_data.emit();
+ ff_addr.width = GetSize(port.addr);
+ ff_addr.has_clk = true;
+ ff_addr.sig_clk = port.clk;
+ ff_addr.pol_clk = port.clk_polarity;
+ ff_addr.sig_d = port.addr;
+ ff_addr.sig_q = new_addr;;
+ ff_addr.val_init = Const(State::Sx, ff_addr.width);
+ ff_addr.emit();
+ ff_en.width = GetSize(compressed.first);
+ ff_en.has_clk = true;
+ ff_en.sig_clk = port.clk;
+ ff_en.pol_clk = port.clk_polarity;
+ ff_en.sig_d = compressed.first;
+ ff_en.sig_q = new_en;;
+ ff_en.val_init = Const(State::S0, ff_en.width);
+ ff_en.emit();
+ port.data = new_data;
+ port.addr = new_addr;
+ port.en = port.decompress_en(compressed.second, new_en);
+ }
+}
+
+std::pair<SigSpec, std::vector<int>> MemWr::compress_en() {
+ SigSpec sig = en[0];
+ std::vector<int> swizzle;
+ SigBit prev_bit = en[0];
+ int idx = 0;
+ for (auto &bit: en) {
+ if (bit != prev_bit) {
+ sig.append(bit);
+ prev_bit = bit;
+ idx++;
+ }
+ swizzle.push_back(idx);
+ }
+ log_assert(idx + 1 == GetSize(sig));
+ return {sig, swizzle};
+}
+
+SigSpec MemWr::decompress_en(const std::vector<int> &swizzle, SigSpec sig) {
+ SigSpec res;
+ for (int i: swizzle)
+ res.append(sig[i]);
+ return res;
+}
diff --git a/kernel/mem.h b/kernel/mem.h
index 6d727e71d..ae87b1285 100644
--- a/kernel/mem.h
+++ b/kernel/mem.h
@@ -21,38 +21,76 @@
#define MEM_H
#include "kernel/yosys.h"
+#include "kernel/ffinit.h"
YOSYS_NAMESPACE_BEGIN
-struct MemRd {
- dict<IdString, Const> attributes;
+struct MemRd : RTLIL::AttrObject {
+ bool removed;
Cell *cell;
- bool clk_enable, clk_polarity;
- bool transparent;
- SigSpec clk, en, addr, data;
- MemRd() : cell(nullptr) {}
+ int wide_log2;
+ bool clk_enable, clk_polarity, ce_over_srst;
+ Const arst_value, srst_value, init_value;
+ // One bit for every write port, true iff simultanous read on this
+ // port and write on the other port will bypass the written data
+ // to this port's output (default behavior is to read old value).
+ // Can only be set for write ports that have the same clock domain.
+ std::vector<bool> transparency_mask;
+ // One bit for every write port, true iff simultanous read on this
+ // port and write on the other port will return an all-X (don't care)
+ // value. Mutually exclusive with transparency_mask.
+ // Can only be set for write ports that have the same clock domain.
+ // For optimization purposes, this will also be set if we can
+ // determine that the two ports can never be active simultanously
+ // (making the above vacuously true).
+ std::vector<bool> collision_x_mask;
+ SigSpec clk, en, arst, srst, addr, data;
+
+ MemRd() : removed(false), cell(nullptr) {}
+
+ // Returns the address of given subword index accessed by this port.
+ SigSpec sub_addr(int sub) {
+ SigSpec res = addr;
+ for (int i = 0; i < wide_log2; i++)
+ res[i] = State(sub >> i & 1);
+ return res;
+ }
};
-struct MemWr {
- dict<IdString, Const> attributes;
+struct MemWr : RTLIL::AttrObject {
+ bool removed;
Cell *cell;
+ int wide_log2;
bool clk_enable, clk_polarity;
+ std::vector<bool> priority_mask;
SigSpec clk, en, addr, data;
- MemWr() : cell(nullptr) {}
+
+ MemWr() : removed(false), cell(nullptr) {}
+
+ // Returns the address of given subword index accessed by this port.
+ SigSpec sub_addr(int sub) {
+ SigSpec res = addr;
+ for (int i = 0; i < wide_log2; i++)
+ res[i] = State(sub >> i & 1);
+ return res;
+ }
+
+ std::pair<SigSpec, std::vector<int>> compress_en();
+ SigSpec decompress_en(const std::vector<int> &swizzle, SigSpec sig);
};
-struct MemInit {
- dict<IdString, Const> attributes;
+struct MemInit : RTLIL::AttrObject {
+ bool removed;
Cell *cell;
Const addr;
Const data;
- MemInit() : cell(nullptr) {}
+ Const en;
+ MemInit() : removed(false), cell(nullptr) {}
};
-struct Mem {
+struct Mem : RTLIL::AttrObject {
Module *module;
IdString memid;
- dict<IdString, Const> attributes;
bool packed;
RTLIL::Memory *mem;
Cell *cell;
@@ -61,15 +99,128 @@ struct Mem {
std::vector<MemRd> rd_ports;
std::vector<MemWr> wr_ports;
+ // Removes this memory from the module. The data in helper structures
+ // is unaffected except for the cell/mem fields.
void remove();
+
+ // Commits all changes in helper structures into the module — ports and
+ // inits marked as removed are actually removed, new ports/inits create
+ // new cells, modified port/inits are commited into their existing
+ // cells. Note that this reindexes the ports and inits array (actually
+ // removing the ports/inits marked as removed).
void emit();
- void remove_wr_port(int idx);
- void remove_rd_port(int idx);
+
+ // Marks all inits as removed.
void clear_inits();
+
+ // Coalesces inits: whenever two inits have overlapping or touching
+ // address ranges, they are combined into one, with the higher-priority
+ // one's data overwriting the other. Running this results in
+ // an inits list equivalent to the original, in which all entries
+ // cover disjoint (and non-touching) address ranges, and all enable
+ // masks are all-1.
+ void coalesce_inits();
+
+ // Checks consistency of this memory and all its ports/inits, using
+ // log_assert.
+ void check();
+
+ // Gathers all initialization data into a single big const covering
+ // the whole memory. For all non-initialized bits, Sx will be returned.
Const get_init_data() const;
+
+ // Constructs and returns the helper structures for all memories
+ // in a module.
static std::vector<Mem> get_all_memories(Module *module);
+
+ // Constructs and returns the helper structures for all selected
+ // memories in a module.
static std::vector<Mem> get_selected_memories(Module *module);
- Cell *extract_rdff(int idx);
+
+ // Converts a synchronous read port into an asynchronous one by
+ // extracting the data (or, in some rare cases, address) register
+ // into a separate cell, together with any soft-transparency
+ // logic necessary to preserve its semantics. Returns the created
+ // register cell, if any. Note that in some rare cases this function
+ // may succeed and perform a conversion without creating a new
+ // register — a nullptr result doesn't imply nothing was done.
+ Cell *extract_rdff(int idx, FfInitVals *initvals);
+
+ // Splits all wide ports in this memory into equivalent narrow ones.
+ // This function performs no modifications at all to the actual
+ // netlist unless and until emit() is called.
+ void narrow();
+
+ // If write port idx2 currently has priority over write port idx1,
+ // inserts extra logic on idx1's enable signal to disable writes
+ // when idx2 is writing to the same address, then removes the priority
+ // from the priority mask. If there is a memory port that is
+ // transparent with idx1, but not with idx2, that port is converted
+ // to use soft transparency logic.
+ void emulate_priority(int idx1, int idx2, FfInitVals *initvals);
+
+ // Creates soft-transparency logic on read port ridx, bypassing the
+ // data from write port widx. Should only be called when ridx is
+ // transparent wrt widx in the first place. Once we're done, the
+ // transparency_mask bit will be cleared, and the collision_x_mask
+ // bit will be set instead (since whatever value is read will be
+ // replaced by the soft transparency logic).
+ void emulate_transparency(int widx, int ridx, FfInitVals *initvals);
+
+ // Prepares for merging write port idx2 into idx1 (where idx1 < idx2).
+ // Specifically, takes care of priority masks: any priority relations
+ // that idx2 had are replicated onto idx1, unless they conflict with
+ // priorities already present on idx1, in which case emulate_priority
+ // is called. Likewise, ensures transparency and undefined collision
+ // masks of all read ports have the same values for both ports,
+ // calling emulate_transparency if necessary.
+ void prepare_wr_merge(int idx1, int idx2, FfInitVals *initvals);
+
+ // Prepares for merging read port idx2 into idx1.
+ // Specifically, makes sure the transparency and undefined collision
+ // masks of both ports are equal, by changing undefined behavior
+ // of one port to the other's defined behavior, or by calling
+ // emulate_transparency if necessary.
+ void prepare_rd_merge(int idx1, int idx2, FfInitVals *initvals);
+
+ // Prepares the memory for widening a port to a given width. This
+ // involves ensuring that start_offset and size are aligned to the
+ // target width.
+ void widen_prep(int wide_log2);
+
+ // Widens a write port up to a given width. The newly port is
+ // equivalent to the original, made by replicating enable/data bits
+ // and masking enable bits with decoders on the low part of the
+ // original address.
+ void widen_wr_port(int idx, int wide_log2);
+
+ // Emulates a sync read port's enable functionality in soft logic,
+ // changing the actual read port's enable to be always-on.
+ void emulate_rden(int idx, FfInitVals *initvals);
+
+ // Emulates a sync read port's initial/reset value functionality in
+ // soft logic, removing it from the actual read port.
+ void emulate_reset(int idx, bool emu_init, bool emu_arst, bool emu_srst, FfInitVals *initvals);
+
+ // Given a read port with ce_over_srst set, converts it to a port
+ // with ce_over_srst unset without changing its behavior by adding
+ // emulation logic.
+ void emulate_rd_ce_over_srst(int idx);
+
+ // Given a read port with ce_over_srst unset, converts it to a port
+ // with ce_over_srst set without changing its behavior by adding
+ // emulation logic.
+ void emulate_rd_srst_over_ce(int idx);
+
+ // Returns true iff emulate_read_first makes sense to call.
+ bool emulate_read_first_ok();
+
+ // Emulates all read-first read-write port relationships in terms of
+ // all-transparent ports, by delaying all write ports by one cycle.
+ // This can only be used when all read ports and all write ports are
+ // in the same clock domain.
+ void emulate_read_first(FfInitVals *initvals);
+
Mem(Module *module, IdString memid, int width, int start_offset, int size) : module(module), memid(memid), packed(false), mem(nullptr), cell(nullptr), width(width), start_offset(start_offset), size(size) {}
};
diff --git a/kernel/modtools.h b/kernel/modtools.h
index 29c510059..4cbaf78d0 100644
--- a/kernel/modtools.h
+++ b/kernel/modtools.h
@@ -1,7 +1,7 @@
/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -380,9 +380,11 @@ struct ModWalker
}
}
- ModWalker(RTLIL::Design *design) : design(design), module(NULL)
+ ModWalker(RTLIL::Design *design, RTLIL::Module *module = nullptr) : design(design), module(NULL)
{
- ct.setup(design);
+ ct.setup(design);
+ if (module)
+ setup(module);
}
void setup(RTLIL::Module *module, CellTypes *filter_ct = NULL)
@@ -395,6 +397,8 @@ struct ModWalker
signal_consumers.clear();
signal_inputs.clear();
signal_outputs.clear();
+ cell_inputs.clear();
+ cell_outputs.clear();
for (auto &it : module->wires_)
add_wire(it.second);
diff --git a/kernel/qcsat.cc b/kernel/qcsat.cc
new file mode 100644
index 000000000..aaee984fb
--- /dev/null
+++ b/kernel/qcsat.cc
@@ -0,0 +1,102 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * 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/qcsat.h"
+
+USING_YOSYS_NAMESPACE
+
+std::vector<int> QuickConeSat::importSig(SigSpec sig)
+{
+ sig = modwalker.sigmap(sig);
+ for (auto bit : sig)
+ bits_queue.insert(bit);
+ return satgen.importSigSpec(sig);
+}
+
+int QuickConeSat::importSigBit(SigBit bit)
+{
+ bit = modwalker.sigmap(bit);
+ bits_queue.insert(bit);
+ return satgen.importSigBit(bit);
+}
+
+void QuickConeSat::prepare()
+{
+ while (!bits_queue.empty())
+ {
+ pool<ModWalker::PortBit> portbits;
+ modwalker.get_drivers(portbits, bits_queue);
+
+ for (auto bit : bits_queue)
+ if (bit.wire && bit.wire->get_bool_attribute(ID::onehot) && !imported_onehot.count(bit.wire))
+ {
+ std::vector<int> bits = satgen.importSigSpec(bit.wire);
+ for (int i : bits)
+ for (int j : bits)
+ if (i != j)
+ ez->assume(ez->NOT(i), j);
+ imported_onehot.insert(bit.wire);
+ }
+
+ bits_queue.clear();
+
+ for (auto &pbit : portbits)
+ {
+ if (imported_cells.count(pbit.cell))
+ continue;
+ if (cell_complexity(pbit.cell) > max_cell_complexity)
+ continue;
+ if (max_cell_outs && GetSize(modwalker.cell_outputs[pbit.cell]) > max_cell_outs)
+ continue;
+ auto &inputs = modwalker.cell_inputs[pbit.cell];
+ bits_queue.insert(inputs.begin(), inputs.end());
+ satgen.importCell(pbit.cell);
+ imported_cells.insert(pbit.cell);
+ }
+
+ if (max_cell_count && GetSize(imported_cells) > max_cell_count)
+ break;
+ }
+}
+
+int QuickConeSat::cell_complexity(RTLIL::Cell *cell)
+{
+ if (cell->type.in(ID($concat), ID($slice), ID($pos), ID($_BUF_)))
+ return 0;
+ if (cell->type.in(ID($not), ID($and), ID($or), ID($xor), ID($xnor),
+ ID($reduce_and), ID($reduce_or), ID($reduce_xor),
+ ID($reduce_xnor), ID($reduce_bool),
+ ID($logic_not), ID($logic_and), ID($logic_or),
+ ID($eq), ID($ne), ID($eqx), ID($nex), ID($fa),
+ ID($mux), ID($pmux), ID($bmux), ID($demux), ID($lut), ID($sop),
+ ID($_NOT_), ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_),
+ ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_),
+ ID($_MUX_), ID($_NMUX_), ID($_MUX4_), ID($_MUX8_), ID($_MUX16_),
+ ID($_AOI3_), ID($_OAI3_), ID($_AOI4_), ID($_OAI4_)))
+ return 1;
+ if (cell->type.in(ID($neg), ID($add), ID($sub), ID($alu), ID($lcu),
+ ID($lt), ID($le), ID($gt), ID($ge)))
+ return 2;
+ if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)))
+ return 3;
+ if (cell->type.in(ID($mul), ID($macc), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow)))
+ return 4;
+ // Unknown cell.
+ return 5;
+}
diff --git a/kernel/qcsat.h b/kernel/qcsat.h
new file mode 100644
index 000000000..e4d3c3c5d
--- /dev/null
+++ b/kernel/qcsat.h
@@ -0,0 +1,76 @@
+/* -*- c++ -*-
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * 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.
+ *
+ */
+
+#ifndef QCSAT_H
+#define QCSAT_H
+
+#include "kernel/satgen.h"
+#include "kernel/modtools.h"
+
+YOSYS_NAMESPACE_BEGIN
+
+// This is a helper class meant for easy construction of quick SAT queries
+// to a combinatorial input cone of some set of signals, meant for SAT-based
+// optimizations. Various knobs are provided to set just how much of the
+// cone should be included in the model — since this class is meant for
+// optimization, it should not be a correctness problem when some cells are
+// skipped and the solver spuriously returns SAT with a solution that
+// cannot exist in reality due to skipped constraints (ie. only UNSAT results
+// from this class should be considered binding).
+struct QuickConeSat {
+ ModWalker &modwalker;
+ ezSatPtr ez;
+ SatGen satgen;
+
+ // The effort level knobs.
+
+ // The maximum "complexity level" of cells that will be imported.
+ // - 1: bitwise operations, muxes, equality comparisons, lut, sop, fa
+ // - 2: addition, subtraction, greater/less than comparisons, lcu
+ // - 3: shifts
+ // - 4: multiplication, division, power
+ int max_cell_complexity = 2;
+ // The maximum number of cells to import, or 0 for no limit.
+ int max_cell_count = 0;
+ // If non-0, skip importing cells with more than this number of output bits.
+ int max_cell_outs = 0;
+
+ // Internal state.
+ pool<RTLIL::Cell*> imported_cells;
+ pool<RTLIL::Wire*> imported_onehot;
+ pool<RTLIL::SigBit> bits_queue;
+
+ QuickConeSat(ModWalker &modwalker) : modwalker(modwalker), ez(), satgen(ez.get(), &modwalker.sigmap) {}
+
+ // Imports a signal into the SAT solver, queues its input cone to be
+ // imported in the next prepare() call.
+ std::vector<int> importSig(SigSpec sig);
+ int importSigBit(SigBit bit);
+
+ // Imports the input cones of all previously importSig'd signals into
+ // the SAT solver.
+ void prepare();
+
+ // Returns the "complexity level" of a given cell.
+ static int cell_complexity(RTLIL::Cell *cell);
+};
+
+YOSYS_NAMESPACE_END
+
+#endif
diff --git a/kernel/register.cc b/kernel/register.cc
index 34735a608..226963fda 100644
--- a/kernel/register.cc
+++ b/kernel/register.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/kernel/register.h b/kernel/register.h
index 5cd849082..15750af2a 100644
--- a/kernel/register.h
+++ b/kernel/register.h
@@ -1,7 +1,7 @@
/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index 1faf376e7..a89edd992 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -20,6 +20,7 @@
#include "kernel/yosys.h"
#include "kernel/macc.h"
#include "kernel/celltypes.h"
+#include "kernel/binding.h"
#include "frontends/verilog/verilog_frontend.h"
#include "frontends/verilog/preproc.h"
#include "backends/rtlil/rtlil_backend.h"
@@ -57,6 +58,8 @@ const pool<IdString> &RTLIL::builtin_ff_cell_types() {
ID($dffsre),
ID($adff),
ID($adffe),
+ ID($aldff),
+ ID($aldffe),
ID($sdff),
ID($sdffe),
ID($sdffce),
@@ -117,6 +120,18 @@ const pool<IdString> &RTLIL::builtin_ff_cell_types() {
ID($_DFFE_PP0P_),
ID($_DFFE_PP1N_),
ID($_DFFE_PP1P_),
+ ID($_ALDFF_NN_),
+ ID($_ALDFF_NP_),
+ ID($_ALDFF_PN_),
+ ID($_ALDFF_PP_),
+ ID($_ALDFFE_NNN_),
+ ID($_ALDFFE_NNP_),
+ ID($_ALDFFE_NPN_),
+ ID($_ALDFFE_NPP_),
+ ID($_ALDFFE_PNN_),
+ ID($_ALDFFE_PNP_),
+ ID($_ALDFFE_PPN_),
+ ID($_ALDFFE_PPP_),
ID($_SDFF_NN0_),
ID($_SDFF_NN1_),
ID($_SDFF_NP0_),
@@ -363,6 +378,26 @@ bool RTLIL::Const::is_fully_undef() const
return true;
}
+bool RTLIL::Const::is_onehot(int *pos) const
+{
+ cover("kernel.rtlil.const.is_onehot");
+
+ bool found = false;
+ for (int i = 0; i < GetSize(*this); i++) {
+ auto &bit = bits[i];
+ if (bit != RTLIL::State::S0 && bit != RTLIL::State::S1)
+ return false;
+ if (bit == RTLIL::State::S1) {
+ if (found)
+ return false;
+ if (pos)
+ *pos = i;
+ found = true;
+ }
+ }
+ return found;
+}
+
bool RTLIL::AttrObject::has_attribute(RTLIL::IdString id) const
{
return attributes.count(id);
@@ -445,6 +480,35 @@ vector<string> RTLIL::AttrObject::get_hdlname_attribute() const
return split_tokens(get_string_attribute(ID::hdlname), " ");
}
+void RTLIL::AttrObject::set_intvec_attribute(RTLIL::IdString id, const vector<int> &data)
+{
+ std::stringstream attrval;
+ for (auto &i : data) {
+ if (attrval.tellp() > 0)
+ attrval << " ";
+ attrval << i;
+ }
+ attributes[id] = RTLIL::Const(attrval.str());
+}
+
+vector<int> RTLIL::AttrObject::get_intvec_attribute(RTLIL::IdString id) const
+{
+ vector<int> data;
+ auto it = attributes.find(id);
+ if (it != attributes.end())
+ for (const auto &s : split_tokens(attributes.at(id).decode_string())) {
+ char *end = nullptr;
+ errno = 0;
+ long value = strtol(s.c_str(), &end, 10);
+ if (end != s.c_str() + s.size())
+ log_cmd_error("Literal for intvec attribute has invalid format");
+ if (errno == ERANGE || value < INT_MIN || value > INT_MAX)
+ log_cmd_error("Literal for intvec attribute is out of range");
+ data.push_back(value);
+ }
+ return data;
+}
+
bool RTLIL::Selection::selected_module(RTLIL::IdString mod_name) const
{
if (full_selection)
@@ -551,8 +615,10 @@ RTLIL::Design::Design()
RTLIL::Design::~Design()
{
- for (auto it = modules_.begin(); it != modules_.end(); ++it)
- delete it->second;
+ for (auto &pr : modules_)
+ delete pr.second;
+ for (auto n : bindings_)
+ delete n;
for (auto n : verilog_packages)
delete n;
for (auto n : verilog_globals)
@@ -580,6 +646,11 @@ RTLIL::Module *RTLIL::Design::module(RTLIL::IdString name)
return modules_.count(name) ? modules_.at(name) : NULL;
}
+const RTLIL::Module *RTLIL::Design::module(RTLIL::IdString name) const
+{
+ return modules_.count(name) ? modules_.at(name) : NULL;
+}
+
RTLIL::Module *RTLIL::Design::top_module()
{
RTLIL::Module *module = nullptr;
@@ -611,9 +682,16 @@ void RTLIL::Design::add(RTLIL::Module *module)
}
}
+void RTLIL::Design::add(RTLIL::Binding *binding)
+{
+ log_assert(binding != nullptr);
+ bindings_.push_back(binding);
+}
+
RTLIL::Module *RTLIL::Design::addModule(RTLIL::IdString name)
{
- log_assert(modules_.count(name) == 0);
+ if (modules_.count(name) != 0)
+ log_error("Attempted to add new module named '%s', but a module by that name already exists\n", name.c_str());
log_assert(refcount_modules_ == 0);
RTLIL::Module *module = new RTLIL::Module;
@@ -807,12 +885,12 @@ std::vector<RTLIL::Module*> RTLIL::Design::selected_whole_modules() const
return result;
}
-std::vector<RTLIL::Module*> RTLIL::Design::selected_whole_modules_warn() const
+std::vector<RTLIL::Module*> RTLIL::Design::selected_whole_modules_warn(bool include_wb) const
{
std::vector<RTLIL::Module*> result;
result.reserve(modules_.size());
for (auto &it : modules_)
- if (it.second->get_blackbox_attribute())
+ if (it.second->get_blackbox_attribute(include_wb))
continue;
else if (selected_whole_module(it.first))
result.push_back(it.second);
@@ -838,14 +916,16 @@ RTLIL::Module::Module()
RTLIL::Module::~Module()
{
- for (auto it = wires_.begin(); it != wires_.end(); ++it)
- delete it->second;
- for (auto it = memories.begin(); it != memories.end(); ++it)
- delete it->second;
- for (auto it = cells_.begin(); it != cells_.end(); ++it)
- delete it->second;
- for (auto it = processes.begin(); it != processes.end(); ++it)
- delete it->second;
+ for (auto &pr : wires_)
+ delete pr.second;
+ for (auto &pr : memories)
+ delete pr.second;
+ for (auto &pr : cells_)
+ delete pr.second;
+ for (auto &pr : processes)
+ delete pr.second;
+ for (auto binding : bindings_)
+ delete binding;
#ifdef WITH_PYTHON
RTLIL::Module::get_all_modules()->erase(hashidx_);
#endif
@@ -885,9 +965,14 @@ void RTLIL::Module::makeblackbox()
set_bool_attribute(ID::blackbox);
}
-void RTLIL::Module::reprocess_module(RTLIL::Design *, const dict<RTLIL::IdString, RTLIL::Module *> &)
+void RTLIL::Module::expand_interfaces(RTLIL::Design *, const dict<RTLIL::IdString, RTLIL::Module *> &)
{
- log_error("Cannot reprocess_module module `%s' !\n", id2cstr(name));
+ log_error("Class doesn't support expand_interfaces (module: `%s')!\n", id2cstr(name));
+}
+
+bool RTLIL::Module::reprocess_if_necessary(RTLIL::Design *)
+{
+ return false;
}
RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, const dict<RTLIL::IdString, RTLIL::Const> &, bool mayfail)
@@ -1166,6 +1251,22 @@ namespace {
return;
}
+ if (cell->type == ID($bmux)) {
+ port(ID::A, param(ID::WIDTH) << param(ID::S_WIDTH));
+ port(ID::S, param(ID::S_WIDTH));
+ port(ID::Y, param(ID::WIDTH));
+ check_expected();
+ return;
+ }
+
+ if (cell->type == ID($demux)) {
+ port(ID::A, param(ID::WIDTH));
+ port(ID::S, param(ID::S_WIDTH));
+ port(ID::Y, param(ID::WIDTH) << param(ID::S_WIDTH));
+ check_expected();
+ return;
+ }
+
if (cell->type == ID($lut)) {
param(ID::LUT);
port(ID::A, param(ID::WIDTH));
@@ -1300,6 +1401,32 @@ namespace {
return;
}
+ if (cell->type == ID($aldff)) {
+ param_bool(ID::CLK_POLARITY);
+ param_bool(ID::ALOAD_POLARITY);
+ port(ID::CLK, 1);
+ port(ID::ALOAD, 1);
+ port(ID::D, param(ID::WIDTH));
+ port(ID::AD, param(ID::WIDTH));
+ port(ID::Q, param(ID::WIDTH));
+ check_expected();
+ return;
+ }
+
+ if (cell->type == ID($aldffe)) {
+ param_bool(ID::CLK_POLARITY);
+ param_bool(ID::EN_POLARITY);
+ param_bool(ID::ALOAD_POLARITY);
+ port(ID::CLK, 1);
+ port(ID::EN, 1);
+ port(ID::ALOAD, 1);
+ port(ID::D, param(ID::WIDTH));
+ port(ID::AD, param(ID::WIDTH));
+ port(ID::Q, param(ID::WIDTH));
+ check_expected();
+ return;
+ }
+
if (cell->type == ID($dlatch)) {
param_bool(ID::EN_POLARITY);
port(ID::EN, 1);
@@ -1366,6 +1493,26 @@ namespace {
return;
}
+ if (cell->type == ID($memrd_v2)) {
+ param(ID::MEMID);
+ param_bool(ID::CLK_ENABLE);
+ param_bool(ID::CLK_POLARITY);
+ param(ID::TRANSPARENCY_MASK);
+ param(ID::COLLISION_X_MASK);
+ param_bool(ID::CE_OVER_SRST);
+ param_bits(ID::ARST_VALUE, param(ID::WIDTH));
+ param_bits(ID::SRST_VALUE, param(ID::WIDTH));
+ param_bits(ID::INIT_VALUE, param(ID::WIDTH));
+ port(ID::CLK, 1);
+ port(ID::EN, 1);
+ port(ID::ARST, 1);
+ port(ID::SRST, 1);
+ port(ID::ADDR, param(ID::ABITS));
+ port(ID::DATA, param(ID::WIDTH));
+ check_expected();
+ return;
+ }
+
if (cell->type == ID($memwr)) {
param(ID::MEMID);
param_bool(ID::CLK_ENABLE);
@@ -1379,6 +1526,20 @@ namespace {
return;
}
+ if (cell->type == ID($memwr_v2)) {
+ param(ID::MEMID);
+ param_bool(ID::CLK_ENABLE);
+ param_bool(ID::CLK_POLARITY);
+ param(ID::PORTID);
+ param(ID::PRIORITY_MASK);
+ port(ID::CLK, 1);
+ port(ID::EN, param(ID::WIDTH));
+ port(ID::ADDR, param(ID::ABITS));
+ port(ID::DATA, param(ID::WIDTH));
+ check_expected();
+ return;
+ }
+
if (cell->type == ID($meminit)) {
param(ID::MEMID);
param(ID::PRIORITY);
@@ -1388,6 +1549,16 @@ namespace {
return;
}
+ if (cell->type == ID($meminit_v2)) {
+ param(ID::MEMID);
+ param(ID::PRIORITY);
+ port(ID::ADDR, param(ID::ABITS));
+ port(ID::DATA, param(ID::WIDTH) * param(ID::WORDS));
+ port(ID::EN, param(ID::WIDTH));
+ check_expected();
+ return;
+ }
+
if (cell->type == ID($mem)) {
param(ID::MEMID);
param(ID::SIZE);
@@ -1410,6 +1581,38 @@ namespace {
return;
}
+ if (cell->type == ID($mem_v2)) {
+ param(ID::MEMID);
+ param(ID::SIZE);
+ param(ID::OFFSET);
+ param(ID::INIT);
+ param_bits(ID::RD_CLK_ENABLE, max(1, param(ID::RD_PORTS)));
+ param_bits(ID::RD_CLK_POLARITY, max(1, param(ID::RD_PORTS)));
+ param_bits(ID::RD_TRANSPARENCY_MASK, max(1, param(ID::RD_PORTS) * param(ID::WR_PORTS)));
+ param_bits(ID::RD_COLLISION_X_MASK, max(1, param(ID::RD_PORTS) * param(ID::WR_PORTS)));
+ param_bits(ID::RD_WIDE_CONTINUATION, max(1, param(ID::RD_PORTS)));
+ param_bits(ID::RD_CE_OVER_SRST, max(1, param(ID::RD_PORTS)));
+ param_bits(ID::RD_ARST_VALUE, param(ID::RD_PORTS) * param(ID::WIDTH));
+ param_bits(ID::RD_SRST_VALUE, param(ID::RD_PORTS) * param(ID::WIDTH));
+ param_bits(ID::RD_INIT_VALUE, param(ID::RD_PORTS) * param(ID::WIDTH));
+ param_bits(ID::WR_CLK_ENABLE, max(1, param(ID::WR_PORTS)));
+ param_bits(ID::WR_CLK_POLARITY, max(1, param(ID::WR_PORTS)));
+ param_bits(ID::WR_WIDE_CONTINUATION, max(1, param(ID::WR_PORTS)));
+ param_bits(ID::WR_PRIORITY_MASK, max(1, param(ID::WR_PORTS) * param(ID::WR_PORTS)));
+ port(ID::RD_CLK, param(ID::RD_PORTS));
+ port(ID::RD_EN, param(ID::RD_PORTS));
+ port(ID::RD_ARST, param(ID::RD_PORTS));
+ port(ID::RD_SRST, param(ID::RD_PORTS));
+ port(ID::RD_ADDR, param(ID::RD_PORTS) * param(ID::ABITS));
+ port(ID::RD_DATA, param(ID::RD_PORTS) * param(ID::WIDTH));
+ port(ID::WR_CLK, param(ID::WR_PORTS));
+ port(ID::WR_EN, param(ID::WR_PORTS) * param(ID::WIDTH));
+ port(ID::WR_ADDR, param(ID::WR_PORTS) * param(ID::ABITS));
+ port(ID::WR_DATA, param(ID::WR_PORTS) * param(ID::WIDTH));
+ check_expected();
+ return;
+ }
+
if (cell->type == ID($tribuf)) {
port(ID::A, param(ID::WIDTH));
port(ID::Y, param(ID::WIDTH));
@@ -1536,6 +1739,15 @@ namespace {
{ port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::R,1); port(ID::E,1); check_expected(); return; }
if (cell->type.in(
+ ID($_ALDFF_NN_), ID($_ALDFF_NP_), ID($_ALDFF_PN_), ID($_ALDFF_PP_)))
+ { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::L,1); port(ID::AD,1); check_expected(); return; }
+
+ if (cell->type.in(
+ ID($_ALDFFE_NNN_), ID($_ALDFFE_NNP_), ID($_ALDFFE_NPN_), ID($_ALDFFE_NPP_),
+ ID($_ALDFFE_PNN_), ID($_ALDFFE_PNP_), ID($_ALDFFE_PPN_), ID($_ALDFFE_PPP_)))
+ { port(ID::D,1); port(ID::Q,1); port(ID::C,1); port(ID::L,1); port(ID::AD,1); port(ID::E,1); check_expected(); return; }
+
+ if (cell->type.in(
ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_)))
{ port(ID::C,1); port(ID::S,1); port(ID::R,1); port(ID::D,1); port(ID::Q,1); check_expected(); return; }
@@ -1640,7 +1852,7 @@ void RTLIL::Module::check()
log_assert(!it.second->type.empty());
for (auto &it2 : it.second->connections()) {
log_assert(!it2.first.empty());
- it2.second.check();
+ it2.second.check(this);
}
for (auto &it2 : it.second->attributes)
log_assert(!it2.first.empty());
@@ -1686,8 +1898,8 @@ void RTLIL::Module::check()
for (auto &it : connections_) {
log_assert(it.first.size() == it.second.size());
log_assert(!it.first.has_const());
- it.first.check();
- it.second.check();
+ it.first.check(this);
+ it.second.check(this);
}
for (auto &it : attributes)
@@ -1813,6 +2025,20 @@ void RTLIL::Module::add(RTLIL::Cell *cell)
cell->module = this;
}
+void RTLIL::Module::add(RTLIL::Process *process)
+{
+ log_assert(!process->name.empty());
+ log_assert(count_id(process->name) == 0);
+ processes[process->name] = process;
+ process->module = this;
+}
+
+void RTLIL::Module::add(RTLIL::Binding *binding)
+{
+ log_assert(binding != nullptr);
+ bindings_.push_back(binding);
+}
+
void RTLIL::Module::remove(const pool<RTLIL::Wire*> &wires)
{
log_assert(refcount_wires_ == 0);
@@ -1869,6 +2095,13 @@ void RTLIL::Module::remove(RTLIL::Cell *cell)
delete cell;
}
+void RTLIL::Module::remove(RTLIL::Process *process)
+{
+ log_assert(processes.count(process->name) != 0);
+ processes.erase(process->name);
+ delete process;
+}
+
void RTLIL::Module::rename(RTLIL::Wire *wire, RTLIL::IdString new_name)
{
log_assert(wires_[wire->name] == wire);
@@ -2094,11 +2327,19 @@ RTLIL::Memory *RTLIL::Module::addMemory(RTLIL::IdString name, const RTLIL::Memor
return mem;
}
+RTLIL::Process *RTLIL::Module::addProcess(RTLIL::IdString name)
+{
+ RTLIL::Process *proc = new RTLIL::Process;
+ proc->name = name;
+ add(proc);
+ return proc;
+}
+
RTLIL::Process *RTLIL::Module::addProcess(RTLIL::IdString name, const RTLIL::Process *other)
{
RTLIL::Process *proc = other->clone();
proc->name = name;
- processes[name] = proc;
+ add(proc);
return proc;
}
@@ -2219,6 +2460,26 @@ DEF_METHOD(Mux, ID($mux), 0)
DEF_METHOD(Pmux, ID($pmux), 1)
#undef DEF_METHOD
+#define DEF_METHOD(_func, _type, _demux) \
+ RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src) { \
+ RTLIL::Cell *cell = addCell(name, _type); \
+ cell->parameters[ID::WIDTH] = _demux ? sig_a.size() : sig_y.size(); \
+ cell->parameters[ID::S_WIDTH] = sig_s.size(); \
+ cell->setPort(ID::A, sig_a); \
+ cell->setPort(ID::S, sig_s); \
+ cell->setPort(ID::Y, sig_y); \
+ cell->set_src_attribute(src); \
+ return cell; \
+ } \
+ RTLIL::SigSpec RTLIL::Module::_func(RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const std::string &src) { \
+ RTLIL::SigSpec sig_y = addWire(NEW_ID, _demux ? sig_a.size() << sig_s.size() : sig_a.size() >> sig_s.size()); \
+ add ## _func(name, sig_a, sig_s, sig_y, src); \
+ return sig_y; \
+ }
+DEF_METHOD(Bmux, ID($bmux), 0)
+DEF_METHOD(Demux, ID($demux), 1)
+#undef DEF_METHOD
+
#define DEF_METHOD_2(_func, _type, _P1, _P2) \
RTLIL::Cell* RTLIL::Module::add ## _func(RTLIL::IdString name, const RTLIL::SigBit &sig1, const RTLIL::SigBit &sig2, const std::string &src) { \
RTLIL::Cell *cell = addCell(name, _type); \
@@ -2533,6 +2794,40 @@ RTLIL::Cell* RTLIL::Module::addAdffe(RTLIL::IdString name, const RTLIL::SigSpec
return cell;
}
+RTLIL::Cell* RTLIL::Module::addAldff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+ const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool aload_polarity, const std::string &src)
+{
+ RTLIL::Cell *cell = addCell(name, ID($aldff));
+ cell->parameters[ID::CLK_POLARITY] = clk_polarity;
+ cell->parameters[ID::ALOAD_POLARITY] = aload_polarity;
+ cell->parameters[ID::WIDTH] = sig_q.size();
+ cell->setPort(ID::CLK, sig_clk);
+ cell->setPort(ID::ALOAD, sig_aload);
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::AD, sig_ad);
+ cell->setPort(ID::Q, sig_q);
+ cell->set_src_attribute(src);
+ return cell;
+}
+
+RTLIL::Cell* RTLIL::Module::addAldffe(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+ const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool en_polarity, bool aload_polarity, const std::string &src)
+{
+ RTLIL::Cell *cell = addCell(name, ID($aldffe));
+ cell->parameters[ID::CLK_POLARITY] = clk_polarity;
+ cell->parameters[ID::EN_POLARITY] = en_polarity;
+ cell->parameters[ID::ALOAD_POLARITY] = aload_polarity;
+ cell->parameters[ID::WIDTH] = sig_q.size();
+ cell->setPort(ID::CLK, sig_clk);
+ cell->setPort(ID::EN, sig_en);
+ cell->setPort(ID::ALOAD, sig_aload);
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::AD, sig_ad);
+ cell->setPort(ID::Q, sig_q);
+ cell->set_src_attribute(src);
+ return cell;
+}
+
RTLIL::Cell* RTLIL::Module::addSdff(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
RTLIL::Const srst_value, bool clk_polarity, bool srst_polarity, const std::string &src)
{
@@ -2723,6 +3018,33 @@ RTLIL::Cell* RTLIL::Module::addAdffeGate(RTLIL::IdString name, const RTLIL::SigS
return cell;
}
+RTLIL::Cell* RTLIL::Module::addAldffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+ const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool aload_polarity, const std::string &src)
+{
+ RTLIL::Cell *cell = addCell(name, stringf("$_ALDFF_%c%c_", clk_polarity ? 'P' : 'N', aload_polarity ? 'P' : 'N'));
+ cell->setPort(ID::C, sig_clk);
+ cell->setPort(ID::L, sig_aload);
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::AD, sig_ad);
+ cell->setPort(ID::Q, sig_q);
+ cell->set_src_attribute(src);
+ return cell;
+}
+
+RTLIL::Cell* RTLIL::Module::addAldffeGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+ const RTLIL::SigSpec &sig_ad, bool clk_polarity, bool en_polarity, bool aload_polarity, const std::string &src)
+{
+ RTLIL::Cell *cell = addCell(name, stringf("$_ALDFFE_%c%c%c_", clk_polarity ? 'P' : 'N', aload_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
+ cell->setPort(ID::C, sig_clk);
+ cell->setPort(ID::L, sig_aload);
+ cell->setPort(ID::E, sig_en);
+ cell->setPort(ID::D, sig_d);
+ cell->setPort(ID::AD, sig_ad);
+ cell->setPort(ID::Q, sig_q);
+ cell->set_src_attribute(src);
+ return cell;
+}
+
RTLIL::Cell* RTLIL::Module::addSdffGate(RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
bool srst_value, bool clk_polarity, bool srst_polarity, const std::string &src)
{
@@ -2894,6 +3216,13 @@ RTLIL::Memory::Memory()
#endif
}
+RTLIL::Process::Process() : module(nullptr)
+{
+ static unsigned int hashidx_count = 123456789;
+ hashidx_count = mkhash_xorshift(hashidx_count);
+ hashidx_ = hashidx_count;
+}
+
RTLIL::Cell::Cell() : module(nullptr)
{
static unsigned int hashidx_count = 123456789;
@@ -3065,14 +3394,21 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
type.begins_with("$verific$") || type.begins_with("$array:") || type.begins_with("$extern:"))
return;
- if (type == ID($mux) || type == ID($pmux)) {
+ if (type == ID($mux) || type == ID($pmux) || type == ID($bmux)) {
parameters[ID::WIDTH] = GetSize(connections_[ID::Y]);
- if (type == ID($pmux))
+ if (type != ID($mux))
parameters[ID::S_WIDTH] = GetSize(connections_[ID::S]);
check();
return;
}
+ if (type == ID($demux)) {
+ parameters[ID::WIDTH] = GetSize(connections_[ID::A]);
+ parameters[ID::S_WIDTH] = GetSize(connections_[ID::S]);
+ check();
+ return;
+ }
+
if (type == ID($lut) || type == ID($sop)) {
parameters[ID::WIDTH] = GetSize(connections_[ID::A]);
return;
@@ -3119,6 +3455,16 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
check();
}
+bool RTLIL::Cell::has_memid() const
+{
+ return type.in(ID($memwr), ID($memwr_v2), ID($memrd), ID($memrd_v2), ID($meminit), ID($meminit_v2));
+}
+
+bool RTLIL::Cell::is_mem_cell() const
+{
+ return type.in(ID($mem), ID($mem_v2)) || has_memid();
+}
+
RTLIL::SigChunk::SigChunk()
{
wire = NULL;
@@ -3275,8 +3621,12 @@ RTLIL::SigSpec::SigSpec(const RTLIL::Const &value)
{
cover("kernel.rtlil.sigspec.init.const");
- chunks_.emplace_back(value);
- width_ = chunks_.back().width;
+ if (GetSize(value) != 0) {
+ chunks_.emplace_back(value);
+ width_ = chunks_.back().width;
+ } else {
+ width_ = 0;
+ }
hash_ = 0;
check();
}
@@ -3285,8 +3635,12 @@ RTLIL::SigSpec::SigSpec(const RTLIL::SigChunk &chunk)
{
cover("kernel.rtlil.sigspec.init.chunk");
- chunks_.emplace_back(chunk);
- width_ = chunks_.back().width;
+ if (chunk.width != 0) {
+ chunks_.emplace_back(chunk);
+ width_ = chunks_.back().width;
+ } else {
+ width_ = 0;
+ }
hash_ = 0;
check();
}
@@ -3295,8 +3649,12 @@ RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire)
{
cover("kernel.rtlil.sigspec.init.wire");
- chunks_.emplace_back(wire);
- width_ = chunks_.back().width;
+ if (wire->width != 0) {
+ chunks_.emplace_back(wire);
+ width_ = chunks_.back().width;
+ } else {
+ width_ = 0;
+ }
hash_ = 0;
check();
}
@@ -3305,8 +3663,12 @@ RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire, int offset, int width)
{
cover("kernel.rtlil.sigspec.init.wire_part");
- chunks_.emplace_back(wire, offset, width);
- width_ = chunks_.back().width;
+ if (width != 0) {
+ chunks_.emplace_back(wire, offset, width);
+ width_ = chunks_.back().width;
+ } else {
+ width_ = 0;
+ }
hash_ = 0;
check();
}
@@ -3315,8 +3677,12 @@ RTLIL::SigSpec::SigSpec(const std::string &str)
{
cover("kernel.rtlil.sigspec.init.str");
- chunks_.emplace_back(str);
- width_ = chunks_.back().width;
+ if (str.size() != 0) {
+ chunks_.emplace_back(str);
+ width_ = chunks_.back().width;
+ } else {
+ width_ = 0;
+ }
hash_ = 0;
check();
}
@@ -3325,7 +3691,8 @@ RTLIL::SigSpec::SigSpec(int val, int width)
{
cover("kernel.rtlil.sigspec.init.int");
- chunks_.emplace_back(val, width);
+ if (width != 0)
+ chunks_.emplace_back(val, width);
width_ = width;
hash_ = 0;
check();
@@ -3335,7 +3702,8 @@ RTLIL::SigSpec::SigSpec(RTLIL::State bit, int width)
{
cover("kernel.rtlil.sigspec.init.state");
- chunks_.emplace_back(bit, width);
+ if (width != 0)
+ chunks_.emplace_back(bit, width);
width_ = width;
hash_ = 0;
check();
@@ -3345,11 +3713,13 @@ RTLIL::SigSpec::SigSpec(const RTLIL::SigBit &bit, int width)
{
cover("kernel.rtlil.sigspec.init.bit");
- if (bit.wire == NULL)
- chunks_.emplace_back(bit.data, width);
- else
- for (int i = 0; i < width; i++)
- chunks_.push_back(bit);
+ if (width != 0) {
+ if (bit.wire == NULL)
+ chunks_.emplace_back(bit.data, width);
+ else
+ for (int i = 0; i < width; i++)
+ chunks_.push_back(bit);
+ }
width_ = width;
hash_ = 0;
check();
@@ -3794,7 +4164,13 @@ void RTLIL::SigSpec::remove_const()
width_ = 0;
for (auto &chunk : chunks_)
if (chunk.wire != NULL) {
- new_chunks.push_back(chunk);
+ if (!new_chunks.empty() &&
+ new_chunks.back().wire == chunk.wire &&
+ new_chunks.back().offset + new_chunks.back().width == chunk.offset) {
+ new_chunks.back().width += chunk.width;
+ } else {
+ new_chunks.push_back(chunk);
+ }
width_ += chunk.width;
}
@@ -3941,7 +4317,7 @@ RTLIL::SigSpec RTLIL::SigSpec::repeat(int num) const
}
#ifndef NDEBUG
-void RTLIL::SigSpec::check() const
+void RTLIL::SigSpec::check(Module *mod) const
{
if (width_ > 64)
{
@@ -3954,6 +4330,7 @@ void RTLIL::SigSpec::check() const
int w = 0;
for (size_t i = 0; i < chunks_.size(); i++) {
const RTLIL::SigChunk &chunk = chunks_[i];
+ log_assert(chunk.width != 0);
if (chunk.wire == NULL) {
if (i > 0)
log_assert(chunks_[i-1].wire != NULL);
@@ -3966,6 +4343,8 @@ void RTLIL::SigSpec::check() const
log_assert(chunk.width >= 0);
log_assert(chunk.offset + chunk.width <= chunk.wire->width);
log_assert(chunk.data.size() == 0);
+ if (mod != nullptr)
+ log_assert(chunk.wire->module == mod);
}
w += chunk.width;
}
@@ -3976,6 +4355,12 @@ void RTLIL::SigSpec::check() const
{
cover("kernel.rtlil.sigspec.check.unpacked");
+ if (mod != nullptr) {
+ for (size_t i = 0; i < bits_.size(); i++)
+ if (bits_[i].wire != nullptr)
+ log_assert(bits_[i].wire->module == mod);
+ }
+
log_assert(width_ == GetSize(bits_));
log_assert(chunks_.empty());
}
@@ -4164,6 +4549,19 @@ bool RTLIL::SigSpec::has_marked_bits() const
return false;
}
+bool RTLIL::SigSpec::is_onehot(int *pos) const
+{
+ cover("kernel.rtlil.sigspec.is_onehot");
+
+ pack();
+ if (!is_fully_const())
+ return false;
+ log_assert(GetSize(chunks_) <= 1);
+ if (width_)
+ return RTLIL::Const(chunks_[0].data).is_onehot(pos);
+ return false;
+}
+
bool RTLIL::SigSpec::as_bool() const
{
cover("kernel.rtlil.sigspec.as_bool");
@@ -4537,6 +4935,7 @@ RTLIL::SyncRule *RTLIL::SyncRule::clone() const
new_syncrule->type = type;
new_syncrule->signal = signal;
new_syncrule->actions = actions;
+ new_syncrule->mem_write_actions = mem_write_actions;
return new_syncrule;
}
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index 6170ea55e..d8300f159 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -1,7 +1,7 @@
/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -69,8 +69,10 @@ namespace RTLIL
struct SigSpec;
struct CaseRule;
struct SwitchRule;
+ struct MemWriteAction;
struct SyncRule;
struct Process;
+ struct Binding;
typedef std::pair<SigSpec, SigSpec> SigSig;
@@ -165,7 +167,8 @@ namespace RTLIL
log_assert(p[0] == '$' || p[0] == '\\');
log_assert(p[1] != 0);
for (const char *c = p; *c; c++)
- log_assert((unsigned)*c > (unsigned)' ');
+ if ((unsigned)*c <= (unsigned)' ')
+ log_error("Found control character or space (0x%02hhx) in string '%s' which is not allowed in RTLIL identifiers\n", *c, p);
#ifndef YOSYS_NO_IDS_REFCNT
if (global_free_idx_list_.empty()) {
@@ -482,6 +485,9 @@ namespace RTLIL
RTLIL::Const const_pos (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
RTLIL::Const const_neg (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
+ RTLIL::Const const_bmux (const RTLIL::Const &arg1, const RTLIL::Const &arg2);
+ RTLIL::Const const_demux (const RTLIL::Const &arg1, const RTLIL::Const &arg2);
+
// This iterator-range-pair is used for Design::modules(), Module::wires() and Module::cells().
// It maintains a reference counter that is used to make sure that the container is not modified while being iterated over.
@@ -660,6 +666,7 @@ struct RTLIL::Const
bool is_fully_ones() const;
bool is_fully_def() const;
bool is_fully_undef() const;
+ bool is_onehot(int *pos = nullptr) const;
inline RTLIL::Const extract(int offset, int len = 1, RTLIL::State padding = RTLIL::State::S0) const {
RTLIL::Const ret;
@@ -714,6 +721,9 @@ struct RTLIL::AttrObject
void set_hdlname_attribute(const vector<string> &hierarchy);
vector<string> get_hdlname_attribute() const;
+
+ void set_intvec_attribute(RTLIL::IdString id, const vector<int> &data);
+ vector<int> get_intvec_attribute(RTLIL::IdString id) const;
};
struct RTLIL::SigChunk
@@ -752,7 +762,7 @@ struct RTLIL::SigBit
SigBit();
SigBit(RTLIL::State bit);
- SigBit(bool bit);
+ explicit SigBit(bool bit);
SigBit(RTLIL::Wire *wire);
SigBit(RTLIL::Wire *wire, int offset);
SigBit(const RTLIL::SigChunk &chunk);
@@ -834,7 +844,7 @@ public:
SigSpec(const std::vector<RTLIL::SigBit> &bits);
SigSpec(const pool<RTLIL::SigBit> &bits);
SigSpec(const std::set<RTLIL::SigBit> &bits);
- SigSpec(bool bit);
+ explicit SigSpec(bool bit);
SigSpec(RTLIL::SigSpec &&other) {
width_ = other.width_;
@@ -932,6 +942,7 @@ public:
bool is_fully_undef() const;
bool has_const() const;
bool has_marked_bits() const;
+ bool is_onehot(int *pos = nullptr) const;
bool as_bool() const;
int as_int(bool is_signed = false) const;
@@ -960,9 +971,9 @@ public:
unsigned int hash() const { if (!hash_) updhash(); return hash_; };
#ifndef NDEBUG
- void check() const;
+ void check(Module *mod = nullptr) const;
#else
- void check() const { }
+ void check(Module *mod = nullptr) const { (void)mod; }
#endif
};
@@ -1029,6 +1040,8 @@ struct RTLIL::Design
int refcount_modules_;
dict<RTLIL::IdString, RTLIL::Module*> modules_;
+ std::vector<RTLIL::Binding*> bindings_;
+
std::vector<AST::AstNode*> verilog_packages, verilog_globals;
std::unique_ptr<define_map_t> verilog_defines;
@@ -1041,6 +1054,7 @@ struct RTLIL::Design
RTLIL::ObjRange<RTLIL::Module*> modules();
RTLIL::Module *module(RTLIL::IdString name);
+ const RTLIL::Module *module(RTLIL::IdString name) const;
RTLIL::Module *top_module();
bool has(RTLIL::IdString id) const {
@@ -1048,6 +1062,8 @@ struct RTLIL::Design
}
void add(RTLIL::Module *module);
+ void add(RTLIL::Binding *binding);
+
RTLIL::Module *addModule(RTLIL::IdString name);
void remove(RTLIL::Module *module);
void rename(RTLIL::Module *module, RTLIL::IdString new_name);
@@ -1110,7 +1126,7 @@ struct RTLIL::Design
std::vector<RTLIL::Module*> selected_modules() const;
std::vector<RTLIL::Module*> selected_whole_modules() const;
- std::vector<RTLIL::Module*> selected_whole_modules_warn() const;
+ std::vector<RTLIL::Module*> selected_whole_modules_warn(bool include_wb = false) const;
#ifdef WITH_PYTHON
static std::map<unsigned int, RTLIL::Design*> *get_all_designs(void);
#endif
@@ -1124,6 +1140,7 @@ struct RTLIL::Module : public RTLIL::AttrObject
protected:
void add(RTLIL::Wire *wire);
void add(RTLIL::Cell *cell);
+ void add(RTLIL::Process *process);
public:
RTLIL::Design *design;
@@ -1134,7 +1151,9 @@ public:
dict<RTLIL::IdString, RTLIL::Wire*> wires_;
dict<RTLIL::IdString, RTLIL::Cell*> cells_;
- std::vector<RTLIL::SigSig> connections_;
+
+ std::vector<RTLIL::SigSig> connections_;
+ std::vector<RTLIL::Binding*> bindings_;
RTLIL::IdString name;
idict<RTLIL::IdString> avail_parameters;
@@ -1147,7 +1166,8 @@ public:
virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool mayfail = false);
virtual RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail = false);
virtual size_t count_id(RTLIL::IdString id);
- virtual void reprocess_module(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces);
+ virtual void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces);
+ virtual bool reprocess_if_necessary(RTLIL::Design *design);
virtual void sort();
virtual void check();
@@ -1189,12 +1209,24 @@ public:
return it == cells_.end() ? nullptr : it->second;
}
+ const RTLIL::Wire* wire(RTLIL::IdString id) const{
+ auto it = wires_.find(id);
+ return it == wires_.end() ? nullptr : it->second;
+ }
+ const RTLIL::Cell* cell(RTLIL::IdString id) const {
+ auto it = cells_.find(id);
+ return it == cells_.end() ? nullptr : it->second;
+ }
+
RTLIL::ObjRange<RTLIL::Wire*> wires() { return RTLIL::ObjRange<RTLIL::Wire*>(&wires_, &refcount_wires_); }
RTLIL::ObjRange<RTLIL::Cell*> cells() { return RTLIL::ObjRange<RTLIL::Cell*>(&cells_, &refcount_cells_); }
+ void add(RTLIL::Binding *binding);
+
// Removing wires is expensive. If you have to remove wires, remove them all at once.
void remove(const pool<RTLIL::Wire*> &wires);
void remove(RTLIL::Cell *cell);
+ void remove(RTLIL::Process *process);
void rename(RTLIL::Wire *wire, RTLIL::IdString new_name);
void rename(RTLIL::Cell *cell, RTLIL::IdString new_name);
@@ -1214,6 +1246,7 @@ public:
RTLIL::Memory *addMemory(RTLIL::IdString name, const RTLIL::Memory *other);
+ RTLIL::Process *addProcess(RTLIL::IdString name);
RTLIL::Process *addProcess(RTLIL::IdString name, const RTLIL::Process *other);
// The add* methods create a cell and return the created cell. All signals must exist in advance.
@@ -1266,6 +1299,8 @@ public:
RTLIL::Cell* addMux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = "");
RTLIL::Cell* addPmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = "");
+ RTLIL::Cell* addBmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = "");
+ RTLIL::Cell* addDemux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const RTLIL::SigSpec &sig_y, const std::string &src = "");
RTLIL::Cell* addSlice (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_y, RTLIL::Const offset, const std::string &src = "");
RTLIL::Cell* addConcat (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_y, const std::string &src = "");
@@ -1286,6 +1321,8 @@ public:
RTLIL::Cell* addDffsre (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = "");
RTLIL::Cell* addAdff (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const arst_value, bool clk_polarity = true, bool arst_polarity = true, const std::string &src = "");
RTLIL::Cell* addAdffe (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const arst_value, bool clk_polarity = true, bool en_polarity = true, bool arst_polarity = true, const std::string &src = "");
+ RTLIL::Cell* addAldff (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const RTLIL::SigSpec &sig_ad, bool clk_polarity = true, bool aload_polarity = true, const std::string &src = "");
+ RTLIL::Cell* addAldffe (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const RTLIL::SigSpec &sig_ad, bool clk_polarity = true, bool en_polarity = true, bool aload_polarity = true, const std::string &src = "");
RTLIL::Cell* addSdff (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const srst_value, bool clk_polarity = true, bool srst_polarity = true, const std::string &src = "");
RTLIL::Cell* addSdffe (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const srst_value, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, const std::string &src = "");
RTLIL::Cell* addSdffce (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const srst_value, bool clk_polarity = true, bool en_polarity = true, bool srst_polarity = true, const std::string &src = "");
@@ -1323,6 +1360,10 @@ public:
bool arst_value = false, bool clk_polarity = true, bool arst_polarity = true, const std::string &src = "");
RTLIL::Cell* addAdffeGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
bool arst_value = false, bool clk_polarity = true, bool en_polarity = true, bool arst_polarity = true, const std::string &src = "");
+ RTLIL::Cell* addAldffGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+ const RTLIL::SigSpec &sig_ad, bool clk_polarity = true, bool aload_polarity = true, const std::string &src = "");
+ RTLIL::Cell* addAldffeGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_aload, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
+ const RTLIL::SigSpec &sig_ad, bool clk_polarity = true, bool en_polarity = true, bool aload_polarity = true, const std::string &src = "");
RTLIL::Cell* addSdffGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
bool srst_value = false, bool clk_polarity = true, bool srst_polarity = true, const std::string &src = "");
RTLIL::Cell* addSdffeGate (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_srst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q,
@@ -1339,7 +1380,6 @@ public:
RTLIL::SigSpec Not (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
RTLIL::SigSpec Pos (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
- RTLIL::SigSpec Bu0 (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
RTLIL::SigSpec Neg (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, bool is_signed = false, const std::string &src = "");
RTLIL::SigSpec And (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, bool is_signed = false, const std::string &src = "");
@@ -1386,6 +1426,8 @@ public:
RTLIL::SigSpec Mux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const std::string &src = "");
RTLIL::SigSpec Pmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_b, const RTLIL::SigSpec &sig_s, const std::string &src = "");
+ RTLIL::SigSpec Bmux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const std::string &src = "");
+ RTLIL::SigSpec Demux (RTLIL::IdString name, const RTLIL::SigSpec &sig_a, const RTLIL::SigSpec &sig_s, const std::string &src = "");
RTLIL::SigBit BufGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const std::string &src = "");
RTLIL::SigBit NotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const std::string &src = "");
@@ -1511,6 +1553,9 @@ public:
#ifdef WITH_PYTHON
static std::map<unsigned int, RTLIL::Cell*> *get_all_cells(void);
#endif
+
+ bool has_memid() const;
+ bool is_mem_cell() const;
};
struct RTLIL::CaseRule : public RTLIL::AttrObject
@@ -1520,7 +1565,6 @@ struct RTLIL::CaseRule : public RTLIL::AttrObject
std::vector<RTLIL::SwitchRule*> switches;
~CaseRule();
- void optimize();
bool empty() const;
@@ -1543,11 +1587,21 @@ struct RTLIL::SwitchRule : public RTLIL::AttrObject
RTLIL::SwitchRule *clone() const;
};
+struct RTLIL::MemWriteAction : RTLIL::AttrObject
+{
+ RTLIL::IdString memid;
+ RTLIL::SigSpec address;
+ RTLIL::SigSpec data;
+ RTLIL::SigSpec enable;
+ RTLIL::Const priority_mask;
+};
+
struct RTLIL::SyncRule
{
RTLIL::SyncType type;
RTLIL::SigSpec signal;
std::vector<RTLIL::SigSig> actions;
+ std::vector<RTLIL::MemWriteAction> mem_write_actions;
template<typename T> void rewrite_sigspecs(T &functor);
template<typename T> void rewrite_sigspecs2(T &functor);
@@ -1556,12 +1610,21 @@ struct RTLIL::SyncRule
struct RTLIL::Process : public RTLIL::AttrObject
{
+ unsigned int hashidx_;
+ unsigned int hash() const { return hashidx_; }
+
+protected:
+ // use module->addProcess() and module->remove() to create or destroy processes
+ friend struct RTLIL::Module;
+ Process();
+ ~Process();
+
+public:
RTLIL::IdString name;
+ RTLIL::Module *module;
RTLIL::CaseRule root_case;
std::vector<RTLIL::SyncRule*> syncs;
- ~Process();
-
template<typename T> void rewrite_sigspecs(T &functor);
template<typename T> void rewrite_sigspecs2(T &functor);
RTLIL::Process *clone() const;
@@ -1695,6 +1758,11 @@ void RTLIL::SyncRule::rewrite_sigspecs(T &functor)
functor(it.first);
functor(it.second);
}
+ for (auto &it : mem_write_actions) {
+ functor(it.address);
+ functor(it.data);
+ functor(it.enable);
+ }
}
template<typename T>
@@ -1704,6 +1772,11 @@ void RTLIL::SyncRule::rewrite_sigspecs2(T &functor)
for (auto &it : actions) {
functor(it.first, it.second);
}
+ for (auto &it : mem_write_actions) {
+ functor(it.address);
+ functor(it.data);
+ functor(it.enable);
+ }
}
template<typename T>
diff --git a/kernel/satgen.cc b/kernel/satgen.cc
index 2a54e78ec..9c40ec66d 100644
--- a/kernel/satgen.cc
+++ b/kernel/satgen.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -252,6 +252,106 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
return true;
}
+ if (cell->type == ID($bmux))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> s = importDefSigSpec(cell->getPort(ID::S), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+ std::vector<int> undef_a, undef_s, undef_y;
+
+ if (model_undef)
+ {
+ undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ undef_s = importUndefSigSpec(cell->getPort(ID::S), timestep);
+ undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ }
+
+ if (GetSize(s) == 0) {
+ ez->vec_set(a, y);
+ if (model_undef)
+ ez->vec_set(undef_a, undef_y);
+ } else {
+ for (int i = GetSize(s)-1; i >= 0; i--)
+ {
+ std::vector<int> out = (i == 0) ? y : ez->vec_var(a.size() / 2);
+ std::vector<int> yy = model_undef ? ez->vec_var(out.size()) : out;
+
+ std::vector<int> a0(a.begin(), a.begin() + a.size() / 2);
+ std::vector<int> a1(a.begin() + a.size() / 2, a.end());
+ ez->assume(ez->vec_eq(ez->vec_ite(s.at(i), a1, a0), yy));
+
+ if (model_undef)
+ {
+ std::vector<int> undef_out = (i == 0) ? undef_y : ez->vec_var(a.size() / 2);
+ std::vector<int> undef_a0(undef_a.begin(), undef_a.begin() + a.size() / 2);
+ std::vector<int> undef_a1(undef_a.begin() + a.size() / 2, undef_a.end());
+ std::vector<int> unequal_ab = ez->vec_not(ez->vec_iff(a0, a1));
+ std::vector<int> undef_ab = ez->vec_or(unequal_ab, ez->vec_or(undef_a0, undef_a1));
+ std::vector<int> yX = ez->vec_ite(undef_s.at(i), undef_ab, ez->vec_ite(s.at(i), undef_a1, undef_a0));
+ ez->assume(ez->vec_eq(yX, undef_out));
+ undefGating(out, yy, undef_out);
+
+ undef_a = undef_out;
+ }
+
+ a = out;
+ }
+ }
+ return true;
+ }
+
+ if (cell->type == ID($demux))
+ {
+ std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
+ std::vector<int> s = importDefSigSpec(cell->getPort(ID::S), timestep);
+ std::vector<int> y = importDefSigSpec(cell->getPort(ID::Y), timestep);
+ std::vector<int> yy = model_undef ? ez->vec_var(y.size()) : y;
+ std::vector<int> undef_a, undef_s, undef_y;
+
+ if (model_undef)
+ {
+ undef_a = importUndefSigSpec(cell->getPort(ID::A), timestep);
+ undef_s = importUndefSigSpec(cell->getPort(ID::S), timestep);
+ undef_y = importUndefSigSpec(cell->getPort(ID::Y), timestep);
+ }
+
+ if (GetSize(s) == 0) {
+ ez->vec_set(a, y);
+ if (model_undef)
+ ez->vec_set(undef_a, undef_y);
+ } else {
+ for (int i = 0; i < (1 << GetSize(s)); i++)
+ {
+ std::vector<int> ss;
+ for (int j = 0; j < GetSize(s); j++) {
+ if (i & 1 << j)
+ ss.push_back(s[j]);
+ else
+ ss.push_back(ez->NOT(s[j]));
+ }
+ int sss = ez->expression(ezSAT::OpAnd, ss);
+
+ for (int j = 0; j < GetSize(a); j++) {
+ ez->SET(ez->AND(sss, a[j]), yy.at(i * GetSize(a) + j));
+ }
+
+ if (model_undef)
+ {
+ int s0 = ez->expression(ezSAT::OpOr, ez->vec_and(ez->vec_not(ss), ez->vec_not(undef_s)));
+ int us = ez->AND(ez->NOT(s0), ez->expression(ezSAT::OpOr, undef_s));
+ for (int j = 0; j < GetSize(a); j++) {
+ int a0 = ez->AND(ez->NOT(a[j]), ez->NOT(undef_a[j]));
+ int yX = ez->AND(ez->OR(us, undef_a[j]), ez->NOT(ez->OR(s0, a0)));
+ ez->SET(yX, undef_y.at(i * GetSize(a) + j));
+ }
+ }
+ }
+ if (model_undef)
+ undefGating(y, yy, undef_y);
+ }
+ return true;
+ }
+
if (cell->type == ID($pmux))
{
std::vector<int> a = importDefSigSpec(cell->getPort(ID::A), timestep);
@@ -1081,7 +1181,7 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
FfData ff(nullptr, cell);
// Latches and FFs with async inputs are not supported — use clk2fflogic or async2sync first.
- if (!ff.has_d || ff.has_arst || ff.has_sr || (ff.has_en && !ff.has_clk))
+ if (ff.has_aload || ff.has_arst || ff.has_sr)
return false;
if (timestep == 1)
@@ -1094,7 +1194,7 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
std::vector<int> undef_d;
if (model_undef)
undef_d = importUndefSigSpec(cell->getPort(ID::D), timestep-1);
- if (ff.has_srst && ff.has_en && ff.ce_over_srst) {
+ if (ff.has_srst && ff.has_ce && ff.ce_over_srst) {
int srst = importDefSigSpec(ff.sig_srst, timestep-1).at(0);
std::vector<int> rval = importDefSigSpec(ff.val_srst, timestep-1);
int undef_srst;
@@ -1108,21 +1208,21 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep)
else
std::tie(d, undef_d) = mux(srst, undef_srst, rval, undef_rval, d, undef_d);
}
- if (ff.has_en) {
- int en = importDefSigSpec(ff.sig_en, timestep-1).at(0);
+ if (ff.has_ce) {
+ int ce = importDefSigSpec(ff.sig_ce, timestep-1).at(0);
std::vector<int> old_q = importDefSigSpec(ff.sig_q, timestep-1);
- int undef_en;
+ int undef_ce;
std::vector<int> undef_old_q;
if (model_undef) {
- undef_en = importUndefSigSpec(ff.sig_en, timestep-1).at(0);
+ undef_ce = importUndefSigSpec(ff.sig_ce, timestep-1).at(0);
undef_old_q = importUndefSigSpec(ff.sig_q, timestep-1);
}
- if (ff.pol_en)
- std::tie(d, undef_d) = mux(en, undef_en, old_q, undef_old_q, d, undef_d);
+ if (ff.pol_ce)
+ std::tie(d, undef_d) = mux(ce, undef_ce, old_q, undef_old_q, d, undef_d);
else
- std::tie(d, undef_d) = mux(en, undef_en, d, undef_d, old_q, undef_old_q);
+ std::tie(d, undef_d) = mux(ce, undef_ce, d, undef_d, old_q, undef_old_q);
}
- if (ff.has_srst && !(ff.has_en && ff.ce_over_srst)) {
+ if (ff.has_srst && !(ff.has_ce && ff.ce_over_srst)) {
int srst = importDefSigSpec(ff.sig_srst, timestep-1).at(0);
std::vector<int> rval = importDefSigSpec(ff.val_srst, timestep-1);
int undef_srst;
diff --git a/kernel/satgen.h b/kernel/satgen.h
index cf2db733f..da2cec222 100644
--- a/kernel/satgen.h
+++ b/kernel/satgen.h
@@ -1,7 +1,7 @@
/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/kernel/sigtools.h b/kernel/sigtools.h
index c631fa481..4ea43d743 100644
--- a/kernel/sigtools.h
+++ b/kernel/sigtools.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/kernel/timinginfo.h b/kernel/timinginfo.h
index eba3386d6..e7e4eab6e 100644
--- a/kernel/timinginfo.h
+++ b/kernel/timinginfo.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* (C) 2020 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -49,9 +49,9 @@ struct TimingInfo
struct ModuleTiming
{
- RTLIL::IdString type;
dict<BitBit, int> comb;
- dict<NameBit, int> arrival, required;
+ dict<NameBit, std::pair<int,NameBit>> arrival, required;
+ bool has_inputs;
};
dict<RTLIL::IdString, ModuleTiming> data;
@@ -120,11 +120,10 @@ struct TimingInfo
}
}
else if (cell->type == ID($specify3)) {
- auto src = cell->getPort(ID::SRC);
+ auto src = cell->getPort(ID::SRC).as_bit();
auto dst = cell->getPort(ID::DST);
- for (const auto &c : src.chunks())
- if (!c.wire->port_input)
- log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src));
+ if (!src.wire || !src.wire->port_input)
+ log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src));
for (const auto &c : dst.chunks())
if (!c.wire->port_output)
log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module output.\n", log_id(module), log_id(cell), log_signal(dst));
@@ -136,34 +135,49 @@ struct TimingInfo
max = 0;
}
for (const auto &d : dst) {
- auto &v = t.arrival[NameBit(d)];
- v = std::max(v, max);
+ auto r = t.arrival.insert(NameBit(d));
+ auto &v = r.first->second;
+ if (r.second || v.first < max) {
+ v.first = max;
+ v.second = NameBit(src);
+ }
}
}
else if (cell->type == ID($specrule)) {
- auto type = cell->getParam(ID::TYPE).decode_string();
- if (type != "$setup" && type != "$setuphold")
+ IdString type = cell->getParam(ID::TYPE).decode_string();
+ if (type != ID($setup) && type != ID($setuphold))
continue;
auto src = cell->getPort(ID::SRC);
- auto dst = cell->getPort(ID::DST);
+ auto dst = cell->getPort(ID::DST).as_bit();
for (const auto &c : src.chunks())
- if (!c.wire->port_input)
+ if (!c.wire || !c.wire->port_input)
log_error("Module '%s' contains specify cell '%s' where SRC '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(src));
- for (const auto &c : dst.chunks())
- if (!c.wire->port_input)
- log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst));
+ if (!dst.wire || !dst.wire->port_input)
+ log_error("Module '%s' contains specify cell '%s' where DST '%s' is not a module input.\n", log_id(module), log_id(cell), log_signal(dst));
int max = cell->getParam(ID::T_LIMIT_MAX).as_int();
if (max < 0) {
log_warning("Module '%s' contains specify cell '%s' with T_LIMIT_MAX < 0 which is currently unsupported. Clamping to 0.\n", log_id(module), log_id(cell));
max = 0;
}
for (const auto &s : src) {
- auto &v = t.required[NameBit(s)];
- v = std::max(v, max);
+ auto r = t.required.insert(NameBit(s));
+ auto &v = r.first->second;
+ if (r.second || v.first < max) {
+ v.first = max;
+ v.second = NameBit(dst);
+ }
}
}
}
+ for (auto port_name : module->ports) {
+ auto wire = module->wire(port_name);
+ if (wire->port_input) {
+ t.has_inputs = true;
+ break;
+ }
+ }
+
return t;
}
diff --git a/kernel/utils.h b/kernel/utils.h
index 8942905fe..d37f045ff 100644
--- a/kernel/utils.h
+++ b/kernel/utils.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/kernel/yosys.cc b/kernel/yosys.cc
index 1caf80c11..09909696b 100644
--- a/kernel/yosys.cc
+++ b/kernel/yosys.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -67,6 +67,7 @@
# define INIT_MODULE initlibyosys
extern "C" void INIT_MODULE();
#endif
+#include <signal.h>
#endif
#include <limits.h>
@@ -137,7 +138,7 @@ void yosys_banner()
log(" | |\n");
log(" | yosys -- Yosys Open SYnthesis Suite |\n");
log(" | |\n");
- log(" | Copyright (C) 2012 - 2020 Claire Wolf <claire@symbioticeda.com> |\n");
+ log(" | Copyright (C) 2012 - 2020 Claire Xenia Wolf <claire@yosyshq.com> |\n");
log(" | |\n");
log(" | Permission to use, copy, modify, and/or distribute this software for any |\n");
log(" | purpose with or without fee is hereby granted, provided that the above |\n");
@@ -540,6 +541,7 @@ void yosys_setup()
PyImport_AppendInittab((char*)"libyosys", INIT_MODULE);
Py_Initialize();
PyRun_SimpleString("import sys");
+ signal(SIGINT, SIG_DFL);
#endif
Pass::init_register();
@@ -814,7 +816,9 @@ std::string proc_self_dirname()
path = (char *) realloc((void *) path, buflen);
while (buflen > 0 && path[buflen-1] != '/')
buflen--;
- return std::string(path, buflen);
+ std::string str(path, buflen);
+ free(path);
+ return str;
}
#elif defined(_WIN32)
std::string proc_self_dirname()
@@ -969,7 +973,7 @@ static void handle_label(std::string &command, bool &from_to_active, const std::
}
}
-void run_frontend(std::string filename, std::string command, std::string *backend_command, std::string *from_to_label, RTLIL::Design *design)
+bool run_frontend(std::string filename, std::string command, RTLIL::Design *design, std::string *from_to_label)
{
if (design == nullptr)
design = yosys_design;
@@ -979,11 +983,11 @@ void run_frontend(std::string filename, std::string command, std::string *backen
if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-3, std::string::npos, ".gz") == 0)
filename_trim.erase(filename_trim.size()-3);
if (filename_trim.size() > 2 && filename_trim.compare(filename_trim.size()-2, std::string::npos, ".v") == 0)
- command = "verilog";
+ command = " -vlog2k";
else if (filename_trim.size() > 2 && filename_trim.compare(filename_trim.size()-3, std::string::npos, ".sv") == 0)
- command = "verilog -sv";
+ command = " -sv";
else if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-4, std::string::npos, ".vhd") == 0)
- command = "vhdl";
+ command = " -vhdl";
else if (filename_trim.size() > 4 && filename_trim.compare(filename_trim.size()-5, std::string::npos, ".blif") == 0)
command = "blif";
else if (filename_trim.size() > 5 && filename_trim.compare(filename_trim.size()-6, std::string::npos, ".eblif") == 0)
@@ -1069,10 +1073,12 @@ void run_frontend(std::string filename, std::string command, std::string *backen
if (filename != "-")
fclose(f);
- if (backend_command != NULL && *backend_command == "auto")
- *backend_command = "";
+ return true;
+ }
- return;
+ if (command == "tcl") {
+ Pass::call(design, vector<string>({command, filename}));
+ return true;
}
if (filename == "-") {
@@ -1081,16 +1087,15 @@ void run_frontend(std::string filename, std::string command, std::string *backen
log("\n-- Parsing `%s' using frontend `%s' --\n", filename.c_str(), command.c_str());
}
- if (command == "tcl")
- Pass::call(design, vector<string>({command, filename}));
- else
+ if (command[0] == ' ') {
+ auto argv = split_tokens("read" + command);
+ argv.push_back(filename);
+ Pass::call(design, argv);
+ } else
Frontend::frontend_call(design, NULL, filename, command);
- design->check();
-}
-void run_frontend(std::string filename, std::string command, RTLIL::Design *design)
-{
- run_frontend(filename, command, nullptr, nullptr, design);
+ design->check();
+ return false;
}
void run_pass(std::string command, RTLIL::Design *design)
@@ -1404,7 +1409,7 @@ struct ScriptCmdPass : public Pass {
else if (args.size() == 2)
run_frontend(args[1], "script", design);
else if (args.size() == 3)
- run_frontend(args[1], "script", NULL, &args[2], design);
+ run_frontend(args[1], "script", design, &args[2]);
else
extra_args(args, 2, design, false);
}
diff --git a/kernel/yosys.h b/kernel/yosys.h
index 5df7e2df0..93e7ff23e 100644
--- a/kernel/yosys.h
+++ b/kernel/yosys.h
@@ -1,7 +1,7 @@
/* -*- c++ -*-
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -33,7 +33,7 @@
// This header is very boring. It just defines some general things that
// belong nowhere else and includes the interesting headers.
//
-// Find more information in the "CodingReadme" file.
+// Find more information in the "guidelines/GettingStarted" file.
#ifndef YOSYS_H
@@ -147,9 +147,7 @@ extern Tcl_Obj *Tcl_ObjSetVar2(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *p
# define YS_ATTRIBUTE(...)
#endif
-#if __cplusplus >= 201703L
-# define YS_MAYBE_UNUSED [[maybe_unused]];
-#elif defined(__GNUC__) || defined(__clang__)
+#if defined(__GNUC__) || defined(__clang__)
# define YS_MAYBE_UNUSED __attribute__((__unused__))
#else
# define YS_MAYBE_UNUSED
@@ -222,6 +220,7 @@ namespace RTLIL {
struct Wire;
struct Cell;
struct Memory;
+ struct Process;
struct Module;
struct Design;
struct Monitor;
@@ -245,6 +244,7 @@ namespace hashlib {
template<> struct hash_ops<RTLIL::Wire*> : hash_obj_ops {};
template<> struct hash_ops<RTLIL::Cell*> : hash_obj_ops {};
template<> struct hash_ops<RTLIL::Memory*> : hash_obj_ops {};
+ template<> struct hash_ops<RTLIL::Process*> : hash_obj_ops {};
template<> struct hash_ops<RTLIL::Module*> : hash_obj_ops {};
template<> struct hash_ops<RTLIL::Design*> : hash_obj_ops {};
template<> struct hash_ops<RTLIL::Monitor*> : hash_obj_ops {};
@@ -253,6 +253,7 @@ namespace hashlib {
template<> struct hash_ops<const RTLIL::Wire*> : hash_obj_ops {};
template<> struct hash_ops<const RTLIL::Cell*> : hash_obj_ops {};
template<> struct hash_ops<const RTLIL::Memory*> : hash_obj_ops {};
+ template<> struct hash_ops<const RTLIL::Process*> : hash_obj_ops {};
template<> struct hash_ops<const RTLIL::Module*> : hash_obj_ops {};
template<> struct hash_ops<const RTLIL::Design*> : hash_obj_ops {};
template<> struct hash_ops<const RTLIL::Monitor*> : hash_obj_ops {};
@@ -349,8 +350,7 @@ std::vector<std::string> glob_filename(const std::string &filename_pattern);
void rewrite_filename(std::string &filename);
void run_pass(std::string command, RTLIL::Design *design = nullptr);
-void run_frontend(std::string filename, std::string command, std::string *backend_command, std::string *from_to_label = nullptr, RTLIL::Design *design = nullptr);
-void run_frontend(std::string filename, std::string command, RTLIL::Design *design = nullptr);
+bool run_frontend(std::string filename, std::string command, RTLIL::Design *design = nullptr, std::string *from_to_label = nullptr);
void run_backend(std::string filename, std::string command, RTLIL::Design *design = nullptr);
void shell(RTLIL::Design *design);
diff --git a/libs/bigint/README b/libs/bigint/README
index e1842381e..c6e9bdba6 100644
--- a/libs/bigint/README
+++ b/libs/bigint/README
@@ -1,5 +1,5 @@
-Note by Clifford Wolf:
+Note by Claire Wolf:
This version of bigint was downloaded at 2012-08-29 from
https://mattmccutchen.net/bigint/bigint-2010.04.30.tar.bz2
diff --git a/libs/ezsat/README b/libs/ezsat/README
index c6745e6cf..db0a18a4e 100644
--- a/libs/ezsat/README
+++ b/libs/ezsat/README
@@ -4,7 +4,7 @@
* The ezSAT C++11 library *
* *
* A simple frontend to SAT solvers with bindings to MiniSAT. *
- * by Clifford Wolf *
+ * by Claire Xenia Wolf *
* *
**************************************************************************
diff --git a/libs/ezsat/demo_bit.cc b/libs/ezsat/demo_bit.cc
index c7b11246c..b4b689701 100644
--- a/libs/ezsat/demo_bit.cc
+++ b/libs/ezsat/demo_bit.cc
@@ -1,7 +1,7 @@
/*
* ezSAT -- A simple and easy to use CNF generator for SAT solvers
*
- * Copyright (C) 2013 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2013 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/libs/ezsat/demo_cmp.cc b/libs/ezsat/demo_cmp.cc
index 8d7ceb2b4..7b927c664 100644
--- a/libs/ezsat/demo_cmp.cc
+++ b/libs/ezsat/demo_cmp.cc
@@ -1,7 +1,7 @@
/*
* ezSAT -- A simple and easy to use CNF generator for SAT solvers
*
- * Copyright (C) 2013 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2013 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/libs/ezsat/demo_vec.cc b/libs/ezsat/demo_vec.cc
index eb8d75997..a13430d55 100644
--- a/libs/ezsat/demo_vec.cc
+++ b/libs/ezsat/demo_vec.cc
@@ -1,7 +1,7 @@
/*
* ezSAT -- A simple and easy to use CNF generator for SAT solvers
*
- * Copyright (C) 2013 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2013 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/libs/ezsat/ezminisat.cc b/libs/ezsat/ezminisat.cc
index ac4defac3..30df625cb 100644
--- a/libs/ezsat/ezminisat.cc
+++ b/libs/ezsat/ezminisat.cc
@@ -1,7 +1,7 @@
/*
* ezSAT -- A simple and easy to use CNF generator for SAT solvers
*
- * Copyright (C) 2013 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2013 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/libs/ezsat/ezminisat.h b/libs/ezsat/ezminisat.h
index 3a34c13c8..92a91d744 100644
--- a/libs/ezsat/ezminisat.h
+++ b/libs/ezsat/ezminisat.h
@@ -1,7 +1,7 @@
/*
* ezSAT -- A simple and easy to use CNF generator for SAT solvers
*
- * Copyright (C) 2013 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2013 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/libs/ezsat/ezsat.cc b/libs/ezsat/ezsat.cc
index 8c666ca1f..3b089ccca 100644
--- a/libs/ezsat/ezsat.cc
+++ b/libs/ezsat/ezsat.cc
@@ -1,7 +1,7 @@
/*
* ezSAT -- A simple and easy to use CNF generator for SAT solvers
*
- * Copyright (C) 2013 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2013 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/libs/ezsat/ezsat.h b/libs/ezsat/ezsat.h
index 85b13685f..7f3bdf68d 100644
--- a/libs/ezsat/ezsat.h
+++ b/libs/ezsat/ezsat.h
@@ -1,7 +1,7 @@
/*
* ezSAT -- A simple and easy to use CNF generator for SAT solvers
*
- * Copyright (C) 2013 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2013 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/libs/ezsat/puzzle3d.cc b/libs/ezsat/puzzle3d.cc
index 59f840f9e..d39def6c6 100644
--- a/libs/ezsat/puzzle3d.cc
+++ b/libs/ezsat/puzzle3d.cc
@@ -1,7 +1,7 @@
/*
* ezSAT -- A simple and easy to use CNF generator for SAT solvers
*
- * Copyright (C) 2013 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2013 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/libs/ezsat/testbench.cc b/libs/ezsat/testbench.cc
index d6dc41fa9..f5a91f3fb 100644
--- a/libs/ezsat/testbench.cc
+++ b/libs/ezsat/testbench.cc
@@ -1,7 +1,7 @@
/*
* ezSAT -- A simple and easy to use CNF generator for SAT solvers
*
- * Copyright (C) 2013 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2013 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/libs/fst/block_format.txt b/libs/fst/block_format.txt
new file mode 100644
index 000000000..e6fe1661b
--- /dev/null
+++ b/libs/fst/block_format.txt
@@ -0,0 +1,130 @@
+See fstapi.h for the values for the FST_BL_XXX enums.
+
+===========================================================================
+
+compressed wrapper (typically over whole file)
+
+uint8_t FST_BL_ZWRAPPER
+uint64_t section length
+uint64_t length of uncompressed data
+[zlib compressed data]
+
+===========================================================================
+
+header block
+
+uint8_t FST_BL_HDR
+uint64_t section length
+uint64_t start time
+uint64_t end time
+double endian test for "e"
+uint64_t memory used by writer
+uint64_t scope creation count
+uint64_t var creation count
+uint64_t max var idcode
+uint64_t vc section count
+int8_t timescale exponent
+[128 bytes] version
+[128 bytes] date
+
+===========================================================================
+
+geometry block
+
+uint8_t FST_BL_GEOM
+uint64_t section length
+uint64_t length of uncompressed geometry data
+uint64_t maxhandle
+[compressed data]
+
+(length of compressed data is section length - 24)
+
+===========================================================================
+
+hierarchy block
+
+uint8_t FST_BL_HIER
+uint64_t section length
+uint64_t length of uncompressed hier data
+[zlib compressed data]
+
+or
+
+uint8_t FST_BL_HIER_LZ4
+uint64_t section length
+uint64_t length of uncompressed hier data
+[lz4 compressed data]
+
+uint8_t FST_BL_HIER_LZ4DUO
+uint64_t section length
+uint64_t length of uncompressed hier data
+varint length of hier data compressed once with lz4
+[lz4 double compressed data]
+
+
+===========================================================================
+
+dumpon/off block
+
+uint8_t FST_BL_BLACKOUT
+uint64_t section length
+varint num blackouts (section below is repeated this # times)
+[
+uint8_t on/off (nonzero = on)
+varint delta time
+]
+
+===========================================================================
+
+1..n value change blocks:
+
+// header
+
+uint8_t FST_BL_VCDATA (or FST_BL_VCDATA_DYN_ALIAS)
+uint64_t section length
+uint64_t begin time of section
+uint64_t end time of section
+uint64_t amount of buffer memory required in reader for full vc traversal
+varint maxvalpos (length of uncompressed data)
+varint length of compressed data
+varint maxhandle associated with this checkpoint data
+[compressed data]
+
+---
+
+// value changes
+
+varint maxhandle associated with the value change data
+uint8_t pack type ('F' is fastlz, '4' is lz4,
+ others ['Z'/'!'] are zlib)
+
+varint chain 0 compressed data length (0 = uncompressed)
+[compressed data]
+...
+varint chain n compressed data length (0 = uncompressed)
+[compressed data]
+
+---
+
+// index: chain pointer table (from 0..maxhandle-1)
+
+varint if &1 == 1, this is <<1 literal delta
+ if &1 == 0, this is <<1 RLE count of zeros
+ if == 0, next varint is handle of prev chain to use,
+ bit only if FST_BL_VCDATA_DYN_ALIAS or
+ later VCDATA format
+
+---
+
+uint64_t index length (subtract from here to get index position)
+
+---
+
+[compressed data for time section]
+uint64_t uncompressed data length in bytes
+uint64_t compressed data length in bytes
+uint64_t number of time items
+
+// end of section
+
+===========================================================================
diff --git a/libs/fst/config.h b/libs/fst/config.h
new file mode 100644
index 000000000..0598fb8c5
--- /dev/null
+++ b/libs/fst/config.h
@@ -0,0 +1,27 @@
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+ */
+#define HAVE_ALLOCA_H 1
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#define HAVE_FSEEKO 1
+
+/* Define to 1 if you have the `pthread' library (-lpthread). */
+#define HAVE_LIBPTHREAD 1
+
+/* Define to 1 if you have the `realpath' function. */
+#define HAVE_REALPATH 1
+
+#if defined(__MINGW32__)
+#undef HAVE_ALLOCA_H
+#undef HAVE_REALPATH
+#endif
+#if defined(_MSC_VER)
+#undef HAVE_ALLOCA_H
+#undef HAVE_REALPATH
+#undef HAVE_LIBPTHREAD
+#undef HAVE_FSEEKO
+#endif
+
+# ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+# endif
diff --git a/libs/fst/fastlz.cc b/libs/fst/fastlz.cc
new file mode 100644
index 000000000..68bda3346
--- /dev/null
+++ b/libs/fst/fastlz.cc
@@ -0,0 +1,528 @@
+/*
+ FastLZ - lightning-fast lossless compression library
+
+ Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+ SPDX-License-Identifier: MIT
+*/
+
+#include "fastlz.h"
+
+#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
+
+/*
+ * Always check for bound when decompressing.
+ * Generally it is best to leave it defined.
+ */
+#define FASTLZ_SAFE
+
+/*
+ * Give hints to the compiler for branch prediction optimization.
+ */
+#if defined(__GNUC__) && (__GNUC__ > 2)
+#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
+#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
+#else
+#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
+#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
+#endif
+
+/*
+ * Use inlined functions for supported systems.
+ */
+#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
+#define FASTLZ_INLINE inline
+#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
+#define FASTLZ_INLINE __inline
+#else
+#define FASTLZ_INLINE
+#endif
+
+/*
+ * Prevent accessing more than 8-bit at once, except on x86 architectures.
+ */
+#if !defined(FASTLZ_STRICT_ALIGN)
+#define FASTLZ_STRICT_ALIGN
+#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__amd64) /* GNU C */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(_M_IX86) /* Intel, MSVC */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__386)
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(_X86_) /* MinGW */
+#undef FASTLZ_STRICT_ALIGN
+#elif defined(__I86__) /* Digital Mars */
+#undef FASTLZ_STRICT_ALIGN
+#endif
+#endif
+
+/* prototypes */
+int fastlz_compress(const void *input, int length, void *output);
+int fastlz_compress_level(int level, const void *input, int length, void *output);
+int fastlz_decompress(const void *input, int length, void *output, int maxout);
+
+#define MAX_COPY 32
+#define MAX_LEN 264 /* 256 + 8 */
+#define MAX_DISTANCE 8192
+
+#if !defined(FASTLZ_STRICT_ALIGN)
+#define FASTLZ_READU16(p) *((const flzuint16 *)(p))
+#else
+#define FASTLZ_READU16(p) ((p)[0] | (p)[1] << 8)
+#endif
+
+#define HASH_LOG 13
+#define HASH_SIZE (1 << HASH_LOG)
+#define HASH_MASK (HASH_SIZE - 1)
+#define HASH_FUNCTION(v, p) \
+ { \
+ v = FASTLZ_READU16(p); \
+ v ^= FASTLZ_READU16(p + 1) ^ (v >> (16 - HASH_LOG)); \
+ v &= HASH_MASK; \
+ }
+
+#undef FASTLZ_LEVEL
+#define FASTLZ_LEVEL 1
+
+#undef FASTLZ_COMPRESSOR
+#undef FASTLZ_DECOMPRESSOR
+#define FASTLZ_COMPRESSOR fastlz1_compress
+#define FASTLZ_DECOMPRESSOR fastlz1_decompress
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void *input, int length, void *output);
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void *input, int length, void *output, int maxout);
+#include "fastlz.cc"
+
+#undef FASTLZ_LEVEL
+#define FASTLZ_LEVEL 2
+
+#undef MAX_DISTANCE
+#define MAX_DISTANCE 8191
+#define MAX_FARDISTANCE (65535 + MAX_DISTANCE - 1)
+
+#undef FASTLZ_COMPRESSOR
+#undef FASTLZ_DECOMPRESSOR
+#define FASTLZ_COMPRESSOR fastlz2_compress
+#define FASTLZ_DECOMPRESSOR fastlz2_decompress
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void *input, int length, void *output);
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void *input, int length, void *output, int maxout);
+#include "fastlz.cc"
+
+int fastlz_compress(const void *input, int length, void *output)
+{
+ /* for short block, choose fastlz1 */
+ if (length < 65536)
+ return fastlz1_compress(input, length, output);
+
+ /* else... */
+ return fastlz2_compress(input, length, output);
+}
+
+int fastlz_decompress(const void *input, int length, void *output, int maxout)
+{
+ /* magic identifier for compression level */
+ int level = ((*(const flzuint8 *)input) >> 5) + 1;
+
+ if (level == 1)
+ return fastlz1_decompress(input, length, output, maxout);
+ if (level == 2)
+ return fastlz2_decompress(input, length, output, maxout);
+
+ /* unknown level, trigger error */
+ return 0;
+}
+
+int fastlz_compress_level(int level, const void *input, int length, void *output)
+{
+ if (level == 1)
+ return fastlz1_compress(input, length, output);
+ if (level == 2)
+ return fastlz2_compress(input, length, output);
+
+ return 0;
+}
+
+#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
+
+static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void *input, int length, void *output)
+{
+ const flzuint8 *ip = (const flzuint8 *)input;
+ const flzuint8 *ip_bound = ip + length - 2;
+ const flzuint8 *ip_limit = ip + length - 12;
+ flzuint8 *op = (flzuint8 *)output;
+
+ const flzuint8 *htab[HASH_SIZE];
+ const flzuint8 **hslot;
+ flzuint32 hval;
+
+ flzuint32 copy;
+
+ /* sanity check */
+ if (FASTLZ_UNEXPECT_CONDITIONAL(length < 4)) {
+ if (length) {
+ /* create literal copy only */
+ *op++ = length - 1;
+ ip_bound++;
+ while (ip <= ip_bound)
+ *op++ = *ip++;
+ return length + 1;
+ } else
+ return 0;
+ }
+
+ /* initializes hash table */
+ for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
+ *hslot = ip;
+
+ /* we start with literal copy */
+ copy = 2;
+ *op++ = MAX_COPY - 1;
+ *op++ = *ip++;
+ *op++ = *ip++;
+
+ /* main loop */
+ while (FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit)) {
+ const flzuint8 *ref;
+ flzuint32 distance;
+
+ /* minimum match length */
+ flzuint32 len = 3;
+
+ /* comparison starting-point */
+ const flzuint8 *anchor = ip;
+
+ /* check for a run */
+#if FASTLZ_LEVEL == 2
+ if (ip[0] == ip[-1] && FASTLZ_READU16(ip - 1) == FASTLZ_READU16(ip + 1)) {
+ distance = 1;
+ /* ip += 3; */ /* scan-build, never used */
+ ref = anchor - 1 + 3;
+ goto match;
+ }
+#endif
+
+ /* find potential match */
+ HASH_FUNCTION(hval, ip);
+ hslot = htab + hval;
+ ref = htab[hval];
+
+ /* calculate distance to the match */
+ distance = anchor - ref;
+
+ /* update hash table */
+ *hslot = anchor;
+
+ /* is this a match? check the first 3 bytes */
+ if (distance == 0 ||
+#if FASTLZ_LEVEL == 1
+ (distance >= MAX_DISTANCE) ||
+#else
+ (distance >= MAX_FARDISTANCE) ||
+#endif
+ *ref++ != *ip++ || *ref++ != *ip++ || *ref++ != *ip++)
+ goto literal;
+
+#if FASTLZ_LEVEL == 2
+ /* far, needs at least 5-byte match */
+ if (distance >= MAX_DISTANCE) {
+ if (*ip++ != *ref++ || *ip++ != *ref++)
+ goto literal;
+ len += 2;
+ }
+
+ match:
+#endif
+
+ /* last matched byte */
+ ip = anchor + len;
+
+ /* distance is biased */
+ distance--;
+
+ if (!distance) {
+ /* zero distance means a run */
+ flzuint8 x = ip[-1];
+ while (ip < ip_bound)
+ if (*ref++ != x)
+ break;
+ else
+ ip++;
+ } else
+ for (;;) {
+ /* safe because the outer check against ip limit */
+ if (*ref++ != *ip++)
+ break;
+ if (*ref++ != *ip++)
+ break;
+ if (*ref++ != *ip++)
+ break;
+ if (*ref++ != *ip++)
+ break;
+ if (*ref++ != *ip++)
+ break;
+ if (*ref++ != *ip++)
+ break;
+ if (*ref++ != *ip++)
+ break;
+ if (*ref++ != *ip++)
+ break;
+ while (ip < ip_bound)
+ if (*ref++ != *ip++)
+ break;
+ break;
+ }
+
+ /* if we have copied something, adjust the copy count */
+ if (copy)
+ /* copy is biased, '0' means 1 byte copy */
+ *(op - copy - 1) = copy - 1;
+ else
+ /* back, to overwrite the copy count */
+ op--;
+
+ /* reset literal counter */
+ copy = 0;
+
+ /* length is biased, '1' means a match of 3 bytes */
+ ip -= 3;
+ len = ip - anchor;
+
+ /* encode the match */
+#if FASTLZ_LEVEL == 2
+ if (distance < MAX_DISTANCE) {
+ if (len < 7) {
+ *op++ = (len << 5) + (distance >> 8);
+ *op++ = (distance & 255);
+ } else {
+ *op++ = (7 << 5) + (distance >> 8);
+ for (len -= 7; len >= 255; len -= 255)
+ *op++ = 255;
+ *op++ = len;
+ *op++ = (distance & 255);
+ }
+ } else {
+ /* far away, but not yet in the another galaxy... */
+ if (len < 7) {
+ distance -= MAX_DISTANCE;
+ *op++ = (len << 5) + 31;
+ *op++ = 255;
+ *op++ = distance >> 8;
+ *op++ = distance & 255;
+ } else {
+ distance -= MAX_DISTANCE;
+ *op++ = (7 << 5) + 31;
+ for (len -= 7; len >= 255; len -= 255)
+ *op++ = 255;
+ *op++ = len;
+ *op++ = 255;
+ *op++ = distance >> 8;
+ *op++ = distance & 255;
+ }
+ }
+#else
+
+ if (FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN - 2))
+ while (len > MAX_LEN - 2) {
+ *op++ = (7 << 5) + (distance >> 8);
+ *op++ = MAX_LEN - 2 - 7 - 2;
+ *op++ = (distance & 255);
+ len -= MAX_LEN - 2;
+ }
+
+ if (len < 7) {
+ *op++ = (len << 5) + (distance >> 8);
+ *op++ = (distance & 255);
+ } else {
+ *op++ = (7 << 5) + (distance >> 8);
+ *op++ = len - 7;
+ *op++ = (distance & 255);
+ }
+#endif
+
+ /* update the hash at match boundary */
+ HASH_FUNCTION(hval, ip);
+ htab[hval] = ip++;
+ HASH_FUNCTION(hval, ip);
+ htab[hval] = ip++;
+
+ /* assuming literal copy */
+ *op++ = MAX_COPY - 1;
+
+ continue;
+
+ literal:
+ *op++ = *anchor++;
+ ip = anchor;
+ copy++;
+ if (FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY)) {
+ copy = 0;
+ *op++ = MAX_COPY - 1;
+ }
+ }
+
+ /* left-over as literal copy */
+ ip_bound++;
+ while (ip <= ip_bound) {
+ *op++ = *ip++;
+ copy++;
+ if (copy == MAX_COPY) {
+ copy = 0;
+ *op++ = MAX_COPY - 1;
+ }
+ }
+
+ /* if we have copied something, adjust the copy length */
+ if (copy)
+ *(op - copy - 1) = copy - 1;
+ else
+ op--;
+
+#if FASTLZ_LEVEL == 2
+ /* marker for fastlz2 */
+ *(flzuint8 *)output |= (1 << 5);
+#endif
+
+ return op - (flzuint8 *)output;
+}
+
+static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void *input, int length, void *output, int maxout)
+{
+ const flzuint8 *ip = (const flzuint8 *)input;
+ const flzuint8 *ip_limit = ip + length;
+ flzuint8 *op = (flzuint8 *)output;
+ flzuint8 *op_limit = op + maxout;
+ flzuint32 ctrl = (*ip++) & 31;
+ int loop = 1;
+
+ do {
+ const flzuint8 *ref = op;
+ flzuint32 len = ctrl >> 5;
+ flzuint32 ofs = (ctrl & 31) << 8;
+
+ if (ctrl >= 32) {
+#if FASTLZ_LEVEL == 2
+ flzuint8 code;
+#endif
+ len--;
+ ref -= ofs;
+ if (len == 7 - 1)
+#if FASTLZ_LEVEL == 1
+ len += *ip++;
+ ref -= *ip++;
+#else
+ do {
+ code = *ip++;
+ len += code;
+ } while (code == 255);
+ code = *ip++;
+ ref -= code;
+
+ /* match from 16-bit distance */
+ if (FASTLZ_UNEXPECT_CONDITIONAL(code == 255))
+ if (FASTLZ_EXPECT_CONDITIONAL(ofs == (31 << 8))) {
+ ofs = (*ip++) << 8;
+ ofs += *ip++;
+ ref = op - ofs - MAX_DISTANCE;
+ }
+#endif
+
+#ifdef FASTLZ_SAFE
+ if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
+ return 0;
+
+ if (FASTLZ_UNEXPECT_CONDITIONAL(ref - 1 < (flzuint8 *)output))
+ return 0;
+#endif
+
+ if (FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
+ ctrl = *ip++;
+ else
+ loop = 0;
+
+ if (ref == op) {
+ /* optimize copy for a run */
+ flzuint8 b = ref[-1];
+ *op++ = b;
+ *op++ = b;
+ *op++ = b;
+ for (; len; --len)
+ *op++ = b;
+ } else {
+#if !defined(FASTLZ_STRICT_ALIGN)
+ const flzuint16 *p;
+ flzuint16 *q;
+#endif
+ /* copy from reference */
+ ref--;
+ *op++ = *ref++;
+ *op++ = *ref++;
+ *op++ = *ref++;
+
+#if !defined(FASTLZ_STRICT_ALIGN)
+ /* copy a byte, so that now it's word aligned */
+ if (len & 1) {
+ *op++ = *ref++;
+ len--;
+ }
+
+ /* copy 16-bit at once */
+ q = (flzuint16 *)op;
+ op += len;
+ p = (const flzuint16 *)ref;
+ for (len >>= 1; len > 4; len -= 4) {
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = *p++;
+ }
+ for (; len; --len)
+ *q++ = *p++;
+#else
+ for (; len; --len)
+ *op++ = *ref++;
+#endif
+ }
+ } else {
+ ctrl++;
+#ifdef FASTLZ_SAFE
+ if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
+ return 0;
+ if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
+ return 0;
+#endif
+
+ *op++ = *ip++;
+ for (--ctrl; ctrl; ctrl--)
+ *op++ = *ip++;
+
+ loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
+ if (loop)
+ ctrl = *ip++;
+ }
+ } while (FASTLZ_EXPECT_CONDITIONAL(loop));
+
+ return op - (flzuint8 *)output;
+}
+
+#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
diff --git a/libs/fst/fastlz.h b/libs/fst/fastlz.h
new file mode 100644
index 000000000..1ce44a32a
--- /dev/null
+++ b/libs/fst/fastlz.h
@@ -0,0 +1,109 @@
+/*
+ FastLZ - lightning-fast lossless compression library
+
+ Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
+ Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+ SPDX-License-Identifier: MIT
+*/
+
+#ifndef FASTLZ_H
+#define FASTLZ_H
+
+#include <inttypes.h>
+
+#define flzuint8 uint8_t
+#define flzuint16 uint16_t
+#define flzuint32 uint32_t
+
+
+#define FASTLZ_VERSION 0x000100
+
+#define FASTLZ_VERSION_MAJOR 0
+#define FASTLZ_VERSION_MINOR 0
+#define FASTLZ_VERSION_REVISION 0
+
+#define FASTLZ_VERSION_STRING "0.1.0"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/**
+ Compress a block of data in the input buffer and returns the size of
+ compressed block. The size of input buffer is specified by length. The
+ minimum input buffer size is 16.
+
+ The output buffer must be at least 5% larger than the input buffer
+ and can not be smaller than 66 bytes.
+
+ If the input is not compressible, the return value might be larger than
+ length (input buffer size).
+
+ The input buffer and the output buffer can not overlap.
+*/
+
+int fastlz_compress(const void* input, int length, void* output);
+
+/**
+ Decompress a block of compressed data and returns the size of the
+ decompressed block. If error occurs, e.g. the compressed data is
+ corrupted or the output buffer is not large enough, then 0 (zero)
+ will be returned instead.
+
+ The input buffer and the output buffer can not overlap.
+
+ Decompression is memory safe and guaranteed not to write the output buffer
+ more than what is specified in maxout.
+ */
+
+int fastlz_decompress(const void* input, int length, void* output, int maxout);
+
+/**
+ Compress a block of data in the input buffer and returns the size of
+ compressed block. The size of input buffer is specified by length. The
+ minimum input buffer size is 16.
+
+ The output buffer must be at least 5% larger than the input buffer
+ and can not be smaller than 66 bytes.
+
+ If the input is not compressible, the return value might be larger than
+ length (input buffer size).
+
+ The input buffer and the output buffer can not overlap.
+
+ Compression level can be specified in parameter level. At the moment,
+ only level 1 and level 2 are supported.
+ Level 1 is the fastest compression and generally useful for short data.
+ Level 2 is slightly slower but it gives better compression ratio.
+
+ Note that the compressed data, regardless of the level, can always be
+ decompressed using the function fastlz_decompress above.
+*/
+
+int fastlz_compress_level(int level, const void* input, int length, void* output);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* FASTLZ_H */
diff --git a/libs/fst/fstapi.cc b/libs/fst/fstapi.cc
new file mode 100644
index 000000000..b79470db3
--- /dev/null
+++ b/libs/fst/fstapi.cc
@@ -0,0 +1,6546 @@
+/*
+ * Copyright (c) 2009-2018 Tony Bybell.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+/*
+ * possible disables:
+ *
+ * FST_DYNAMIC_ALIAS_DISABLE : dynamic aliases are not processed
+ * FST_DYNAMIC_ALIAS2_DISABLE : new encoding for dynamic aliases is not generated
+ * FST_WRITEX_DISABLE : fast write I/O routines are disabled
+ *
+ * possible enables:
+ *
+ * FST_DEBUG : not for production use, only enable for development
+ * FST_REMOVE_DUPLICATE_VC : glitch removal (has writer performance impact)
+ * HAVE_LIBPTHREAD -> FST_WRITER_PARALLEL : enables inclusion of parallel writer code
+ * FST_DO_MISALIGNED_OPS (defined automatically for x86 and some others) : CPU architecture can handle misaligned
+ * loads/stores _WAVE_HAVE_JUDY : use Judy arrays instead of Jenkins (undefine if LGPL is not acceptable)
+ *
+ */
+
+#ifndef FST_CONFIG_INCLUDE
+#define FST_CONFIG_INCLUDE "config.h"
+#endif
+#include FST_CONFIG_INCLUDE
+
+#include "fstapi.h"
+#include "fastlz.h"
+#include "lz4.h"
+#include <errno.h>
+
+#ifndef HAVE_LIBPTHREAD
+#undef FST_WRITER_PARALLEL
+#endif
+
+#ifdef FST_WRITER_PARALLEL
+#include <pthread.h>
+#endif
+
+#ifdef __MINGW32__
+#include <windows.h>
+#endif
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#elif defined(__GNUC__)
+#ifndef __MINGW32__
+#ifndef alloca
+#define alloca __builtin_alloca
+#endif
+#else
+#include <malloc.h>
+#endif
+#elif defined(_MSC_VER)
+#include <malloc.h>
+#define alloca _alloca
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX (4096)
+#endif
+
+#if defined(_MSC_VER)
+typedef int64_t fst_off_t;
+#else
+typedef off_t fst_off_t;
+#endif
+
+/* note that Judy versus Jenkins requires more experimentation: they are */
+/* functionally equivalent though it appears Jenkins is slightly faster. */
+/* in addition, Jenkins is not bound by the LGPL. */
+#ifdef _WAVE_HAVE_JUDY
+#include <Judy.h>
+#else
+/* should be more than enough for fstWriterSetSourceStem() */
+#define FST_PATH_HASHMASK ((1UL << 16) - 1)
+typedef const void *Pcvoid_t;
+typedef void *Pvoid_t;
+typedef void **PPvoid_t;
+#define JudyHSIns(a, b, c, d) JenkinsIns((a), (b), (c), (hashmask))
+#define JudyHSFreeArray(a, b) JenkinsFree((a), (hashmask))
+void JenkinsFree(void *base_i, uint32_t hashmask);
+void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint32_t hashmask);
+#endif
+
+#ifndef FST_WRITEX_DISABLE
+#define FST_WRITEX_MAX (64 * 1024)
+#else
+#define fstWritex(a, b, c) fstFwrite((b), (c), 1, fv)
+#endif
+
+/* these defines have a large impact on writer speed when a model has a */
+/* huge number of symbols. as a default, use 128MB and increment when */
+/* every 1M signals are defined. */
+#define FST_BREAK_SIZE (1UL << 27)
+#define FST_BREAK_ADD_SIZE (1UL << 22)
+#define FST_BREAK_SIZE_MAX (1UL << 31)
+#define FST_ACTIVATE_HUGE_BREAK (1000000)
+#define FST_ACTIVATE_HUGE_INC (1000000)
+
+#define FST_WRITER_STR "fstWriter"
+#define FST_ID_NAM_SIZ (512)
+#define FST_ID_NAM_ATTR_SIZ (65536 + 4096)
+#define FST_DOUBLE_ENDTEST (2.7182818284590452354)
+#define FST_HDR_SIM_VERSION_SIZE (128)
+#define FST_HDR_DATE_SIZE (119)
+#define FST_HDR_FILETYPE_SIZE (1)
+#define FST_HDR_TIMEZERO_SIZE (8)
+#define FST_GZIO_LEN (32768)
+#define FST_HDR_FOURPACK_DUO_SIZE (4 * 1024 * 1024)
+
+#if defined(__i386__) || defined(__x86_64__) || defined(_AIX)
+#define FST_DO_MISALIGNED_OPS
+#endif
+
+#if defined(__APPLE__) && defined(__MACH__)
+#define FST_MACOSX
+#include <sys/sysctl.h>
+#endif
+
+#ifdef __GNUC__
+/* Boolean expression more often true than false */
+#define FST_LIKELY(x) __builtin_expect(!!(x), 1)
+/* Boolean expression more often false than true */
+#define FST_UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+#define FST_LIKELY(x) (!!(x))
+#define FST_UNLIKELY(x) (!!(x))
+#endif
+
+#define FST_APIMESS "FSTAPI | "
+
+/***********************/
+/*** ***/
+/*** common function ***/
+/*** ***/
+/***********************/
+
+#if defined(__MINGW32__) || defined(_MSC_VER)
+#include <io.h>
+#ifndef HAVE_FSEEKO
+#define ftello _ftelli64
+#define fseeko _fseeki64
+#endif
+#endif
+
+/*
+ * the recoded "extra" values...
+ * note that FST_RCV_Q is currently unused and is for future expansion.
+ * its intended use is as another level of escape such that any arbitrary
+ * value can be stored as the value: { time_delta, 8 bits, FST_RCV_Q }.
+ * this is currently not implemented so that the branchless decode is:
+ * uint32_t shcnt = 2 << (vli & 1); tdelta = vli >> shcnt;
+ */
+#define FST_RCV_X (1 | (0 << 1))
+#define FST_RCV_Z (1 | (1 << 1))
+#define FST_RCV_H (1 | (2 << 1))
+#define FST_RCV_U (1 | (3 << 1))
+#define FST_RCV_W (1 | (4 << 1))
+#define FST_RCV_L (1 | (5 << 1))
+#define FST_RCV_D (1 | (6 << 1))
+#define FST_RCV_Q (1 | (7 << 1))
+
+#define FST_RCV_STR "xzhuwl-?"
+/* 01234567 */
+
+/*
+ * prevent old file overwrite when currently being read
+ */
+static FILE *unlink_fopen(const char *nam, const char *mode)
+{
+ unlink(nam);
+ return (fopen(nam, mode));
+}
+
+/*
+ * system-specific temp file handling
+ */
+#ifdef __MINGW32__
+
+static FILE *tmpfile_open(char **nam)
+{
+ char *fname = NULL;
+ TCHAR szTempFileName[MAX_PATH];
+ TCHAR lpTempPathBuffer[MAX_PATH];
+ DWORD dwRetVal = 0;
+ UINT uRetVal = 0;
+ FILE *fh = NULL;
+
+ if (nam) /* cppcheck warning fix: nam is always defined, so this is not needed */
+ {
+ dwRetVal = GetTempPath(MAX_PATH, lpTempPathBuffer);
+ if ((dwRetVal > MAX_PATH) || (dwRetVal == 0)) {
+ fprintf(stderr, FST_APIMESS "GetTempPath() failed in " __FILE__ " line %d, exiting.\n", __LINE__);
+ exit(255);
+ } else {
+ uRetVal = GetTempFileName(lpTempPathBuffer, TEXT("FSTW"), 0, szTempFileName);
+ if (uRetVal == 0) {
+ fprintf(stderr, FST_APIMESS "GetTempFileName() failed in " __FILE__ " line %d, exiting.\n", __LINE__);
+ exit(255);
+ } else {
+ fname = strdup(szTempFileName);
+ }
+ }
+
+ if (fname) {
+ *nam = fname;
+ fh = unlink_fopen(fname, "w+b");
+ }
+ }
+
+ return (fh);
+}
+
+#else
+
+static FILE *tmpfile_open(char **nam)
+{
+ FILE *f = tmpfile(); /* replace with mkstemp() + fopen(), etc if this is not good enough */
+ if (nam) {
+ *nam = NULL;
+ }
+ return (f);
+}
+
+#endif
+
+static void tmpfile_close(FILE **f, char **nam)
+{
+ if (f) {
+ if (*f) {
+ fclose(*f);
+ *f = NULL;
+ }
+ }
+
+ if (nam) {
+ if (*nam) {
+ unlink(*nam);
+ free(*nam);
+ *nam = NULL;
+ }
+ }
+}
+
+/*****************************************/
+
+/*
+ * to remove warn_unused_result compile time messages
+ * (in the future there needs to be results checking)
+ */
+static size_t fstFread(void *buf, size_t siz, size_t cnt, FILE *fp) { return (fread(buf, siz, cnt, fp)); }
+
+static size_t fstFwrite(const void *buf, size_t siz, size_t cnt, FILE *fp) { return (fwrite(buf, siz, cnt, fp)); }
+
+static int fstFtruncate(int fd, fst_off_t length) { return (ftruncate(fd, length)); }
+
+/*
+ * realpath compatibility
+ */
+static char *fstRealpath(const char *path, char *resolved_path)
+{
+#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH
+#if (defined(__MACH__) && defined(__APPLE__))
+ if (!resolved_path) {
+ resolved_path = (char *)malloc(PATH_MAX + 1); /* fixes bug on Leopard when resolved_path == NULL */
+ }
+#endif
+
+ return (realpath(path, resolved_path));
+
+#else
+#ifdef __MINGW32__
+ if (!resolved_path) {
+ resolved_path = (char *)malloc(PATH_MAX + 1);
+ }
+ return (_fullpath(resolved_path, path, PATH_MAX));
+#else
+ (void)path;
+ (void)resolved_path;
+ return (NULL);
+#endif
+#endif
+}
+
+/*
+ * mmap compatibility
+ */
+#if defined __CYGWIN__ || defined __MINGW32__ || defined _MSC_VER
+#include <limits.h>
+#define fstMmap(__addr, __len, __prot, __flags, __fd, __off) fstMmap2((__len), (__fd), (__off))
+#define fstMunmap(__addr, __len) free(__addr)
+
+static void *fstMmap2(size_t __len, int __fd, fst_off_t __off)
+{
+ (void)__off;
+
+ unsigned char *pnt = (unsigned char *)malloc(__len);
+ fst_off_t cur_offs = lseek(__fd, 0, SEEK_CUR);
+ size_t i;
+
+ lseek(__fd, 0, SEEK_SET);
+ for (i = 0; i < __len; i += SSIZE_MAX) {
+ read(__fd, pnt + i, ((__len - i) >= SSIZE_MAX) ? SSIZE_MAX : (__len - i));
+ }
+ lseek(__fd, cur_offs, SEEK_SET);
+ return (pnt);
+}
+#else
+#include <sys/mman.h>
+#if defined(__SUNPRO_C)
+#define FST_CADDR_T_CAST (caddr_t)
+#else
+#define FST_CADDR_T_CAST
+#endif
+#define fstMmap(__addr, __len, __prot, __flags, __fd, __off) \
+ (void *)mmap(FST_CADDR_T_CAST(__addr), (__len), (__prot), (__flags), (__fd), (__off))
+#define fstMunmap(__addr, __len) \
+ { \
+ if (__addr) \
+ munmap(FST_CADDR_T_CAST(__addr), (__len)); \
+ }
+#endif
+
+/*
+ * regular and variable-length integer access functions
+ */
+#ifdef FST_DO_MISALIGNED_OPS
+#define fstGetUint32(x) (*(uint32_t *)(x))
+#else
+static uint32_t fstGetUint32(unsigned char *mem)
+{
+ uint32_t u32;
+ unsigned char *buf = (unsigned char *)(&u32);
+
+ buf[0] = mem[0];
+ buf[1] = mem[1];
+ buf[2] = mem[2];
+ buf[3] = mem[3];
+
+ return (*(uint32_t *)buf);
+}
+#endif
+
+static int fstWriterUint64(FILE *handle, uint64_t v)
+{
+ unsigned char buf[8];
+ int i;
+
+ for (i = 7; i >= 0; i--) {
+ buf[i] = v & 0xff;
+ v >>= 8;
+ }
+
+ fstFwrite(buf, 8, 1, handle);
+ return (8);
+}
+
+static uint64_t fstReaderUint64(FILE *f)
+{
+ uint64_t val = 0;
+ unsigned char buf[sizeof(uint64_t)];
+ unsigned int i;
+
+ fstFread(buf, sizeof(uint64_t), 1, f);
+ for (i = 0; i < sizeof(uint64_t); i++) {
+ val <<= 8;
+ val |= buf[i];
+ }
+
+ return (val);
+}
+
+static uint32_t fstGetVarint32(unsigned char *mem, int *skiplen)
+{
+ unsigned char *mem_orig = mem;
+ uint32_t rc = 0;
+ while (*mem & 0x80) {
+ mem++;
+ }
+
+ *skiplen = mem - mem_orig + 1;
+ for (;;) {
+ rc <<= 7;
+ rc |= (uint32_t)(*mem & 0x7f);
+ if (mem == mem_orig) {
+ break;
+ }
+ mem--;
+ }
+
+ return (rc);
+}
+
+static uint32_t fstGetVarint32Length(unsigned char *mem)
+{
+ unsigned char *mem_orig = mem;
+
+ while (*mem & 0x80) {
+ mem++;
+ }
+
+ return (mem - mem_orig + 1);
+}
+
+static uint32_t fstGetVarint32NoSkip(unsigned char *mem)
+{
+ unsigned char *mem_orig = mem;
+ uint32_t rc = 0;
+ while (*mem & 0x80) {
+ mem++;
+ }
+
+ for (;;) {
+ rc <<= 7;
+ rc |= (uint32_t)(*mem & 0x7f);
+ if (mem == mem_orig) {
+ break;
+ }
+ mem--;
+ }
+
+ return (rc);
+}
+
+static unsigned char *fstCopyVarint32ToLeft(unsigned char *pnt, uint32_t v)
+{
+ unsigned char *spnt;
+ uint32_t nxt = v;
+ int cnt = 1;
+ int i;
+
+ while ((nxt = nxt >> 7)) /* determine len to avoid temp buffer copying to cut down on load-hit-store */
+ {
+ cnt++;
+ }
+
+ pnt -= cnt;
+ spnt = pnt;
+ cnt--;
+
+ for (i = 0; i < cnt; i++) /* now generate left to right as normal */
+ {
+ nxt = v >> 7;
+ *(spnt++) = ((unsigned char)v) | 0x80;
+ v = nxt;
+ }
+ *spnt = (unsigned char)v;
+
+ return (pnt);
+}
+
+static unsigned char *fstCopyVarint64ToRight(unsigned char *pnt, uint64_t v)
+{
+ uint64_t nxt;
+
+ while ((nxt = v >> 7)) {
+ *(pnt++) = ((unsigned char)v) | 0x80;
+ v = nxt;
+ }
+ *(pnt++) = (unsigned char)v;
+
+ return (pnt);
+}
+
+static uint64_t fstGetVarint64(unsigned char *mem, int *skiplen)
+{
+ unsigned char *mem_orig = mem;
+ uint64_t rc = 0;
+ while (*mem & 0x80) {
+ mem++;
+ }
+
+ *skiplen = mem - mem_orig + 1;
+ for (;;) {
+ rc <<= 7;
+ rc |= (uint64_t)(*mem & 0x7f);
+ if (mem == mem_orig) {
+ break;
+ }
+ mem--;
+ }
+
+ return (rc);
+}
+
+static uint32_t fstReaderVarint32(FILE *f)
+{
+ unsigned char buf[5];
+ unsigned char *mem = buf;
+ uint32_t rc = 0;
+ int ch;
+
+ do {
+ ch = fgetc(f);
+ *(mem++) = ch;
+ } while (ch & 0x80);
+ mem--;
+
+ for (;;) {
+ rc <<= 7;
+ rc |= (uint32_t)(*mem & 0x7f);
+ if (mem == buf) {
+ break;
+ }
+ mem--;
+ }
+
+ return (rc);
+}
+
+static uint32_t fstReaderVarint32WithSkip(FILE *f, uint32_t *skiplen)
+{
+ unsigned char buf[5];
+ unsigned char *mem = buf;
+ uint32_t rc = 0;
+ int ch;
+
+ do {
+ ch = fgetc(f);
+ *(mem++) = ch;
+ } while (ch & 0x80);
+ *skiplen = mem - buf;
+ mem--;
+
+ for (;;) {
+ rc <<= 7;
+ rc |= (uint32_t)(*mem & 0x7f);
+ if (mem == buf) {
+ break;
+ }
+ mem--;
+ }
+
+ return (rc);
+}
+
+static uint64_t fstReaderVarint64(FILE *f)
+{
+ unsigned char buf[16];
+ unsigned char *mem = buf;
+ uint64_t rc = 0;
+ int ch;
+
+ do {
+ ch = fgetc(f);
+ *(mem++) = ch;
+ } while (ch & 0x80);
+ mem--;
+
+ for (;;) {
+ rc <<= 7;
+ rc |= (uint64_t)(*mem & 0x7f);
+ if (mem == buf) {
+ break;
+ }
+ mem--;
+ }
+
+ return (rc);
+}
+
+static int fstWriterVarint(FILE *handle, uint64_t v)
+{
+ uint64_t nxt;
+ unsigned char buf[10]; /* ceil(64/7) = 10 */
+ unsigned char *pnt = buf;
+ int len;
+
+ while ((nxt = v >> 7)) {
+ *(pnt++) = ((unsigned char)v) | 0x80;
+ v = nxt;
+ }
+ *(pnt++) = (unsigned char)v;
+
+ len = pnt - buf;
+ fstFwrite(buf, len, 1, handle);
+ return (len);
+}
+
+/* signed integer read/write routines are currently unused */
+static int64_t fstGetSVarint64(unsigned char *mem, int *skiplen)
+{
+ unsigned char *mem_orig = mem;
+ int64_t rc = 0;
+ const int64_t one = 1;
+ const int siz = sizeof(int64_t) * 8;
+ int shift = 0;
+ unsigned char byt;
+
+ do {
+ byt = *(mem++);
+ rc |= ((int64_t)(byt & 0x7f)) << shift;
+ shift += 7;
+
+ } while (byt & 0x80);
+
+ if ((shift < siz) && (byt & 0x40)) {
+ rc |= -(one << shift); /* sign extend */
+ }
+
+ *skiplen = mem - mem_orig;
+
+ return (rc);
+}
+
+#ifndef FST_DYNAMIC_ALIAS2_DISABLE
+static int fstWriterSVarint(FILE *handle, int64_t v)
+{
+ unsigned char buf[15]; /* ceil(64/7) = 10 + sign byte padded way up */
+ unsigned char byt;
+ unsigned char *pnt = buf;
+ int more = 1;
+ int len;
+
+ do {
+ byt = v | 0x80;
+ v >>= 7;
+
+ if (((!v) && (!(byt & 0x40))) || ((v == -1) && (byt & 0x40))) {
+ more = 0;
+ byt &= 0x7f;
+ }
+
+ *(pnt++) = byt;
+ } while (more);
+
+ len = pnt - buf;
+ fstFwrite(buf, len, 1, handle);
+ return (len);
+}
+#endif
+
+/***********************/
+/*** ***/
+/*** writer function ***/
+/*** ***/
+/***********************/
+
+/*
+ * private structs
+ */
+struct fstBlackoutChain
+{
+ struct fstBlackoutChain *next;
+ uint64_t tim;
+ unsigned active : 1;
+};
+
+struct fstWriterContext
+{
+ FILE *handle;
+ FILE *hier_handle;
+ FILE *geom_handle;
+ FILE *valpos_handle;
+ FILE *curval_handle;
+ FILE *tchn_handle;
+
+ unsigned char *vchg_mem;
+
+ fst_off_t hier_file_len;
+
+ uint32_t *valpos_mem;
+ unsigned char *curval_mem;
+
+ unsigned char *outval_mem; /* for two-state / Verilator-style value changes */
+ uint32_t outval_alloc_siz;
+
+ char *filename;
+
+ fstHandle maxhandle;
+ fstHandle numsigs;
+ uint32_t maxvalpos;
+
+ unsigned vc_emitted : 1;
+ unsigned is_initial_time : 1;
+ unsigned fourpack : 1;
+ unsigned fastpack : 1;
+
+ int64_t timezero;
+ fst_off_t section_header_truncpos;
+ uint32_t tchn_cnt, tchn_idx;
+ uint64_t curtime;
+ uint64_t firsttime;
+ uint32_t vchg_siz;
+ uint32_t vchg_alloc_siz;
+
+ uint32_t secnum;
+ fst_off_t section_start;
+
+ uint32_t numscopes;
+ double nan; /* nan value for uninitialized doubles */
+
+ struct fstBlackoutChain *blackout_head;
+ struct fstBlackoutChain *blackout_curr;
+ uint32_t num_blackouts;
+
+ uint64_t dump_size_limit;
+
+ unsigned char filetype; /* default is 0, FST_FT_VERILOG */
+
+ unsigned compress_hier : 1;
+ unsigned repack_on_close : 1;
+ unsigned skip_writing_section_hdr : 1;
+ unsigned size_limit_locked : 1;
+ unsigned section_header_only : 1;
+ unsigned flush_context_pending : 1;
+ unsigned parallel_enabled : 1;
+ unsigned parallel_was_enabled : 1;
+
+ /* should really be semaphores, but are bytes to cut down on read-modify-write window size */
+ unsigned char already_in_flush; /* in case control-c handlers interrupt */
+ unsigned char already_in_close; /* in case control-c handlers interrupt */
+
+#ifdef FST_WRITER_PARALLEL
+ pthread_mutex_t mutex;
+ pthread_t thread;
+ pthread_attr_t thread_attr;
+ struct fstWriterContext *xc_parent;
+#endif
+ unsigned in_pthread : 1;
+
+ size_t fst_orig_break_size;
+ size_t fst_orig_break_add_size;
+
+ size_t fst_break_size;
+ size_t fst_break_add_size;
+
+ size_t fst_huge_break_size;
+
+ fstHandle next_huge_break;
+
+ Pvoid_t path_array;
+ uint32_t path_array_count;
+
+ unsigned fseek_failed : 1;
+
+ char *geom_handle_nam;
+ char *valpos_handle_nam;
+ char *curval_handle_nam;
+ char *tchn_handle_nam;
+
+ fstEnumHandle max_enumhandle;
+};
+
+static int fstWriterFseeko(struct fstWriterContext *xc, FILE *stream, fst_off_t offset, int whence)
+{
+ int rc = fseeko(stream, offset, whence);
+
+ if (rc < 0) {
+ xc->fseek_failed = 1;
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "Seek to #%" PRId64 " (whence = %d) failed!\n", offset, whence);
+ perror("Why");
+#endif
+ }
+
+ return (rc);
+}
+
+static uint32_t fstWriterUint32WithVarint32(struct fstWriterContext *xc, uint32_t *u, uint32_t v, const void *dbuf,
+ uint32_t siz)
+{
+ unsigned char *buf = xc->vchg_mem + xc->vchg_siz;
+ unsigned char *pnt = buf;
+ uint32_t nxt;
+ uint32_t len;
+
+#ifdef FST_DO_MISALIGNED_OPS
+ (*(uint32_t *)(pnt)) = (*(uint32_t *)(u));
+#else
+ memcpy(pnt, u, sizeof(uint32_t));
+#endif
+ pnt += 4;
+
+ while ((nxt = v >> 7)) {
+ *(pnt++) = ((unsigned char)v) | 0x80;
+ v = nxt;
+ }
+ *(pnt++) = (unsigned char)v;
+ memcpy(pnt, dbuf, siz);
+
+ len = pnt - buf + siz;
+ return (len);
+}
+
+static uint32_t fstWriterUint32WithVarint32AndLength(struct fstWriterContext *xc, uint32_t *u, uint32_t v,
+ const void *dbuf, uint32_t siz)
+{
+ unsigned char *buf = xc->vchg_mem + xc->vchg_siz;
+ unsigned char *pnt = buf;
+ uint32_t nxt;
+ uint32_t len;
+
+#ifdef FST_DO_MISALIGNED_OPS
+ (*(uint32_t *)(pnt)) = (*(uint32_t *)(u));
+#else
+ memcpy(pnt, u, sizeof(uint32_t));
+#endif
+ pnt += 4;
+
+ while ((nxt = v >> 7)) {
+ *(pnt++) = ((unsigned char)v) | 0x80;
+ v = nxt;
+ }
+ *(pnt++) = (unsigned char)v;
+
+ v = siz;
+ while ((nxt = v >> 7)) {
+ *(pnt++) = ((unsigned char)v) | 0x80;
+ v = nxt;
+ }
+ *(pnt++) = (unsigned char)v;
+
+ memcpy(pnt, dbuf, siz);
+
+ len = pnt - buf + siz;
+ return (len);
+}
+
+/*
+ * header bytes, write here so defines are set up before anything else
+ * that needs to use them
+ */
+static void fstWriterEmitHdrBytes(struct fstWriterContext *xc)
+{
+ char vbuf[FST_HDR_SIM_VERSION_SIZE];
+ char dbuf[FST_HDR_DATE_SIZE];
+ double endtest = FST_DOUBLE_ENDTEST;
+ time_t walltime;
+
+#define FST_HDR_OFFS_TAG (0)
+ fputc(FST_BL_HDR, xc->handle); /* +0 tag */
+
+#define FST_HDR_OFFS_SECLEN (FST_HDR_OFFS_TAG + 1)
+ fstWriterUint64(xc->handle, 329); /* +1 section length */
+
+#define FST_HDR_OFFS_START_TIME (FST_HDR_OFFS_SECLEN + 8)
+ fstWriterUint64(xc->handle, 0); /* +9 start time */
+
+#define FST_HDR_OFFS_END_TIME (FST_HDR_OFFS_START_TIME + 8)
+ fstWriterUint64(xc->handle, 0); /* +17 end time */
+
+#define FST_HDR_OFFS_ENDIAN_TEST (FST_HDR_OFFS_END_TIME + 8)
+ fstFwrite(&endtest, 8, 1, xc->handle); /* +25 endian test for reals */
+
+#define FST_HDR_OFFS_MEM_USED (FST_HDR_OFFS_ENDIAN_TEST + 8)
+ fstWriterUint64(xc->handle, xc->fst_break_size); /* +33 memory used by writer */
+
+#define FST_HDR_OFFS_NUM_SCOPES (FST_HDR_OFFS_MEM_USED + 8)
+ fstWriterUint64(xc->handle, 0); /* +41 scope creation count */
+
+#define FST_HDR_OFFS_NUM_VARS (FST_HDR_OFFS_NUM_SCOPES + 8)
+ fstWriterUint64(xc->handle, 0); /* +49 var creation count */
+
+#define FST_HDR_OFFS_MAXHANDLE (FST_HDR_OFFS_NUM_VARS + 8)
+ fstWriterUint64(xc->handle, 0); /* +57 max var idcode */
+
+#define FST_HDR_OFFS_SECTION_CNT (FST_HDR_OFFS_MAXHANDLE + 8)
+ fstWriterUint64(xc->handle, 0); /* +65 vc section count */
+
+#define FST_HDR_OFFS_TIMESCALE (FST_HDR_OFFS_SECTION_CNT + 8)
+ fputc((-9) & 255, xc->handle); /* +73 timescale 1ns */
+
+#define FST_HDR_OFFS_SIM_VERSION (FST_HDR_OFFS_TIMESCALE + 1)
+ memset(vbuf, 0, FST_HDR_SIM_VERSION_SIZE);
+ strcpy(vbuf, FST_WRITER_STR);
+ fstFwrite(vbuf, FST_HDR_SIM_VERSION_SIZE, 1, xc->handle); /* +74 version */
+
+#define FST_HDR_OFFS_DATE (FST_HDR_OFFS_SIM_VERSION + FST_HDR_SIM_VERSION_SIZE)
+ memset(dbuf, 0, FST_HDR_DATE_SIZE);
+ time(&walltime);
+ strcpy(dbuf, asctime(localtime(&walltime)));
+ fstFwrite(dbuf, FST_HDR_DATE_SIZE, 1, xc->handle); /* +202 date */
+
+ /* date size is deliberately overspecified at 119 bytes (originally 128) in order to provide backfill for new args
+ */
+
+#define FST_HDR_OFFS_FILETYPE (FST_HDR_OFFS_DATE + FST_HDR_DATE_SIZE)
+ fputc(xc->filetype, xc->handle); /* +321 filetype */
+
+#define FST_HDR_OFFS_TIMEZERO (FST_HDR_OFFS_FILETYPE + FST_HDR_FILETYPE_SIZE)
+ fstWriterUint64(xc->handle, xc->timezero); /* +322 timezero */
+
+#define FST_HDR_LENGTH (FST_HDR_OFFS_TIMEZERO + FST_HDR_TIMEZERO_SIZE)
+ /* +330 next section starts here */
+ fflush(xc->handle);
+}
+
+/*
+ * mmap functions
+ */
+static void fstWriterMmapSanity(void *pnt, const char *file, int line, const char *usage)
+{
+#if !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(_MSC_VER)
+ if (pnt == MAP_FAILED) {
+ fprintf(stderr, "fstMmap() assigned to %s failed: errno: %d, file %s, line %d.\n", usage, errno, file, line);
+ perror("Why");
+ pnt = NULL;
+ }
+#endif
+}
+
+static void fstWriterCreateMmaps(struct fstWriterContext *xc)
+{
+ fst_off_t curpos = ftello(xc->handle);
+
+ fflush(xc->hier_handle);
+
+ /* write out intermediate header */
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_START_TIME, SEEK_SET);
+ fstWriterUint64(xc->handle, xc->firsttime);
+ fstWriterUint64(xc->handle, xc->curtime);
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_NUM_SCOPES, SEEK_SET);
+ fstWriterUint64(xc->handle, xc->numscopes);
+ fstWriterUint64(xc->handle, xc->numsigs);
+ fstWriterUint64(xc->handle, xc->maxhandle);
+ fstWriterUint64(xc->handle, xc->secnum);
+ fstWriterFseeko(xc, xc->handle, curpos, SEEK_SET);
+ fflush(xc->handle);
+
+ /* do mappings */
+ if (!xc->valpos_mem) {
+ fflush(xc->valpos_handle);
+ errno = 0;
+ if (xc->maxhandle) {
+ fstWriterMmapSanity(xc->valpos_mem = (uint32_t *)fstMmap(NULL, xc->maxhandle * 4 * sizeof(uint32_t),
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ fileno(xc->valpos_handle), 0),
+ __FILE__, __LINE__, "xc->valpos_mem");
+ }
+ }
+ if (!xc->curval_mem) {
+ fflush(xc->curval_handle);
+ errno = 0;
+ if (xc->maxvalpos) {
+ fstWriterMmapSanity(xc->curval_mem = (unsigned char *)fstMmap(NULL, xc->maxvalpos, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fileno(xc->curval_handle), 0),
+ __FILE__, __LINE__, "xc->curval_handle");
+ }
+ }
+}
+
+static void fstDestroyMmaps(struct fstWriterContext *xc, int is_closing)
+{
+#if !defined __CYGWIN__ && !defined __MINGW32__
+ (void)is_closing;
+#endif
+
+ fstMunmap(xc->valpos_mem, xc->maxhandle * 4 * sizeof(uint32_t));
+ xc->valpos_mem = NULL;
+
+#if defined __CYGWIN__ || defined __MINGW32__
+ if (xc->curval_mem) {
+ if (!is_closing) /* need to flush out for next emulated mmap() read */
+ {
+ unsigned char *pnt = xc->curval_mem;
+ int __fd = fileno(xc->curval_handle);
+ fst_off_t cur_offs = lseek(__fd, 0, SEEK_CUR);
+ size_t i;
+ size_t __len = xc->maxvalpos;
+
+ lseek(__fd, 0, SEEK_SET);
+ for (i = 0; i < __len; i += SSIZE_MAX) {
+ write(__fd, pnt + i, ((__len - i) >= SSIZE_MAX) ? SSIZE_MAX : (__len - i));
+ }
+ lseek(__fd, cur_offs, SEEK_SET);
+ }
+ }
+#endif
+
+ fstMunmap(xc->curval_mem, xc->maxvalpos);
+ xc->curval_mem = NULL;
+}
+
+/*
+ * set up large and small memory usages
+ * crossover point in model is FST_ACTIVATE_HUGE_BREAK number of signals
+ */
+static void fstDetermineBreakSize(struct fstWriterContext *xc)
+{
+#if defined(__linux__) || defined(FST_MACOSX)
+ int was_set = 0;
+
+#ifdef __linux__
+ FILE *f = fopen("/proc/meminfo", "rb");
+
+ if (f) {
+ char buf[257];
+ char *s;
+ while (!feof(f)) {
+ buf[0] = 0;
+ s = fgets(buf, 256, f);
+ if (s && *s) {
+ if (!strncmp(s, "MemTotal:", 9)) {
+ size_t v = atol(s + 10);
+ v *= 1024; /* convert to bytes */
+ v /= 8; /* chop down to 1/8 physical memory */
+ if (v > FST_BREAK_SIZE) {
+ if (v > FST_BREAK_SIZE_MAX) {
+ v = FST_BREAK_SIZE_MAX;
+ }
+
+ xc->fst_huge_break_size = v;
+ was_set = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ fclose(f);
+ }
+
+ if (!was_set) {
+ xc->fst_huge_break_size = FST_BREAK_SIZE;
+ }
+#else
+ int mib[2];
+ int64_t v;
+ size_t length;
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_MEMSIZE;
+ length = sizeof(int64_t);
+ if (!sysctl(mib, 2, &v, &length, NULL, 0)) {
+ v /= 8;
+
+ if (v > (int64_t)FST_BREAK_SIZE) {
+ if (v > (int64_t)FST_BREAK_SIZE_MAX) {
+ v = FST_BREAK_SIZE_MAX;
+ }
+
+ xc->fst_huge_break_size = v;
+ was_set = 1;
+ }
+ }
+
+ if (!was_set) {
+ xc->fst_huge_break_size = FST_BREAK_SIZE;
+ }
+#endif
+#else
+ xc->fst_huge_break_size = FST_BREAK_SIZE;
+#endif
+
+ xc->fst_break_size = xc->fst_orig_break_size = FST_BREAK_SIZE;
+ xc->fst_break_add_size = xc->fst_orig_break_add_size = FST_BREAK_ADD_SIZE;
+ xc->next_huge_break = FST_ACTIVATE_HUGE_BREAK;
+}
+
+/*
+ * file creation and close
+ */
+void *fstWriterCreate(const char *nam, int use_compressed_hier)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)calloc(1, sizeof(struct fstWriterContext));
+
+ xc->compress_hier = use_compressed_hier;
+ fstDetermineBreakSize(xc);
+
+ if ((!nam) || (!(xc->handle = unlink_fopen(nam, "w+b")))) {
+ free(xc);
+ xc = NULL;
+ } else {
+ int flen = strlen(nam);
+ char *hf = (char *)calloc(1, flen + 6);
+
+ memcpy(hf, nam, flen);
+ strcpy(hf + flen, ".hier");
+ xc->hier_handle = unlink_fopen(hf, "w+b");
+
+ xc->geom_handle = tmpfile_open(&xc->geom_handle_nam); /* .geom */
+ xc->valpos_handle = tmpfile_open(&xc->valpos_handle_nam); /* .offs */
+ xc->curval_handle = tmpfile_open(&xc->curval_handle_nam); /* .bits */
+ xc->tchn_handle = tmpfile_open(&xc->tchn_handle_nam); /* .tchn */
+ xc->vchg_alloc_siz = xc->fst_break_size + xc->fst_break_add_size;
+ xc->vchg_mem = (unsigned char *)malloc(xc->vchg_alloc_siz);
+
+ if (xc->hier_handle && xc->geom_handle && xc->valpos_handle && xc->curval_handle && xc->vchg_mem &&
+ xc->tchn_handle) {
+ xc->filename = strdup(nam);
+ xc->is_initial_time = 1;
+
+ fstWriterEmitHdrBytes(xc);
+ xc->nan = strtod("NaN", NULL);
+#ifdef FST_WRITER_PARALLEL
+ pthread_mutex_init(&xc->mutex, NULL);
+ pthread_attr_init(&xc->thread_attr);
+ pthread_attr_setdetachstate(&xc->thread_attr, PTHREAD_CREATE_DETACHED);
+#endif
+ } else {
+ fclose(xc->handle);
+ if (xc->hier_handle) {
+ fclose(xc->hier_handle);
+ unlink(hf);
+ }
+ tmpfile_close(&xc->geom_handle, &xc->geom_handle_nam);
+ tmpfile_close(&xc->valpos_handle, &xc->valpos_handle_nam);
+ tmpfile_close(&xc->curval_handle, &xc->curval_handle_nam);
+ tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam);
+ free(xc->vchg_mem);
+ free(xc);
+ xc = NULL;
+ }
+
+ free(hf);
+ }
+
+ return (xc);
+}
+
+/*
+ * generation and writing out of value change data sections
+ */
+static void fstWriterEmitSectionHeader(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc) {
+ unsigned long destlen;
+ unsigned char *dmem;
+ int rc;
+
+ destlen = xc->maxvalpos;
+ dmem = (unsigned char *)malloc(compressBound(destlen));
+ rc = compress2(dmem, &destlen, xc->curval_mem, xc->maxvalpos,
+ 4); /* was 9...which caused performance drag on traces with many signals */
+
+ fputc(FST_BL_SKIP, xc->handle); /* temporarily tag the section, use FST_BL_VCDATA on finalize */
+ xc->section_start = ftello(xc->handle);
+#ifdef FST_WRITER_PARALLEL
+ if (xc->xc_parent)
+ xc->xc_parent->section_start = xc->section_start;
+#endif
+ xc->section_header_only = 1; /* indicates truncate might be needed */
+ fstWriterUint64(xc->handle, 0); /* placeholder = section length */
+ fstWriterUint64(xc->handle, xc->is_initial_time ? xc->firsttime : xc->curtime); /* begin time of section */
+ fstWriterUint64(xc->handle, xc->curtime); /* end time of section (placeholder) */
+ fstWriterUint64(xc->handle,
+ 0); /* placeholder = amount of buffer memory required in reader for full vc traversal */
+ fstWriterVarint(xc->handle, xc->maxvalpos); /* maxvalpos = length of uncompressed data */
+
+ if ((rc == Z_OK) && (destlen < xc->maxvalpos)) {
+ fstWriterVarint(xc->handle, destlen); /* length of compressed data */
+ } else {
+ fstWriterVarint(xc->handle, xc->maxvalpos); /* length of (unable to be) compressed data */
+ }
+ fstWriterVarint(xc->handle,
+ xc->maxhandle); /* max handle associated with this data (in case of dynamic facility adds) */
+
+ if ((rc == Z_OK) && (destlen < xc->maxvalpos)) {
+ fstFwrite(dmem, destlen, 1, xc->handle);
+ } else /* comparison between compressed / decompressed len tells if compressed */
+ {
+ fstFwrite(xc->curval_mem, xc->maxvalpos, 1, xc->handle);
+ }
+
+ free(dmem);
+ }
+}
+
+/*
+ * only to be called directly by fst code...otherwise must
+ * be synced up with time changes
+ */
+#ifdef FST_WRITER_PARALLEL
+static void fstWriterFlushContextPrivate2(void *ctx)
+#else
+static void fstWriterFlushContextPrivate(void *ctx)
+#endif
+{
+#ifdef FST_DEBUG
+ int cnt = 0;
+#endif
+ unsigned int i;
+ unsigned char *vchg_mem;
+ FILE *f;
+ fst_off_t fpos, indxpos, endpos;
+ uint32_t prevpos;
+ int zerocnt;
+ unsigned char *scratchpad;
+ unsigned char *scratchpnt;
+ unsigned char *tmem;
+ fst_off_t tlen;
+ fst_off_t unc_memreq = 0; /* for reader */
+ unsigned char *packmem;
+ unsigned int packmemlen;
+ uint32_t *vm4ip;
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+#ifdef FST_WRITER_PARALLEL
+ struct fstWriterContext *xc2 = xc->xc_parent;
+#else
+ struct fstWriterContext *xc2 = xc;
+#endif
+
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ Pvoid_t PJHSArray = (Pvoid_t)NULL;
+#ifndef _WAVE_HAVE_JUDY
+ uint32_t hashmask = xc->maxhandle;
+ hashmask |= hashmask >> 1;
+ hashmask |= hashmask >> 2;
+ hashmask |= hashmask >> 4;
+ hashmask |= hashmask >> 8;
+ hashmask |= hashmask >> 16;
+#endif
+#endif
+
+ if ((xc->vchg_siz <= 1) || (xc->already_in_flush))
+ return;
+ xc->already_in_flush = 1; /* should really do this with a semaphore */
+
+ xc->section_header_only = 0;
+ scratchpad = (unsigned char *)malloc(xc->vchg_siz);
+
+ vchg_mem = xc->vchg_mem;
+
+ f = xc->handle;
+ fstWriterVarint(f, xc->maxhandle); /* emit current number of handles */
+ fputc(xc->fourpack ? '4' : (xc->fastpack ? 'F' : 'Z'), f);
+ fpos = 1;
+
+ packmemlen = 1024; /* maintain a running "longest" allocation to */
+ packmem = (unsigned char *)malloc(packmemlen); /* prevent continual malloc...free every loop iter */
+
+ for (i = 0; i < xc->maxhandle; i++) {
+ vm4ip = &(xc->valpos_mem[4 * i]);
+
+ if (vm4ip[2]) {
+ uint32_t offs = vm4ip[2];
+ uint32_t next_offs;
+ unsigned int wrlen;
+
+ vm4ip[2] = fpos;
+
+ scratchpnt = scratchpad + xc->vchg_siz; /* build this buffer backwards */
+ if (vm4ip[1] <= 1) {
+ if (vm4ip[1] == 1) {
+ wrlen = fstGetVarint32Length(vchg_mem + offs + 4); /* used to advance and determine wrlen */
+#ifndef FST_REMOVE_DUPLICATE_VC
+ xc->curval_mem[vm4ip[0]] = vchg_mem[offs + 4 + wrlen]; /* checkpoint variable */
+#endif
+ while (offs) {
+ unsigned char val;
+ uint32_t time_delta, rcv;
+ next_offs = fstGetUint32(vchg_mem + offs);
+ offs += 4;
+
+ time_delta = fstGetVarint32(vchg_mem + offs, (int *)&wrlen);
+ val = vchg_mem[offs + wrlen];
+ offs = next_offs;
+
+ switch (val) {
+ case '0':
+ case '1':
+ rcv = ((val & 1) << 1) | (time_delta << 2);
+ break; /* pack more delta bits in for 0/1 vchs */
+
+ case 'x':
+ case 'X':
+ rcv = FST_RCV_X | (time_delta << 4);
+ break;
+ case 'z':
+ case 'Z':
+ rcv = FST_RCV_Z | (time_delta << 4);
+ break;
+ case 'h':
+ case 'H':
+ rcv = FST_RCV_H | (time_delta << 4);
+ break;
+ case 'u':
+ case 'U':
+ rcv = FST_RCV_U | (time_delta << 4);
+ break;
+ case 'w':
+ case 'W':
+ rcv = FST_RCV_W | (time_delta << 4);
+ break;
+ case 'l':
+ case 'L':
+ rcv = FST_RCV_L | (time_delta << 4);
+ break;
+ default:
+ rcv = FST_RCV_D | (time_delta << 4);
+ break;
+ }
+
+ scratchpnt = fstCopyVarint32ToLeft(scratchpnt, rcv);
+ }
+ } else {
+ /* variable length */
+ /* fstGetUint32 (next_offs) + fstGetVarint32 (time_delta) + fstGetVarint32 (len) + payload */
+ unsigned char *pnt;
+ uint32_t record_len;
+ uint32_t time_delta;
+
+ while (offs) {
+ next_offs = fstGetUint32(vchg_mem + offs);
+ offs += 4;
+ pnt = vchg_mem + offs;
+ offs = next_offs;
+ time_delta = fstGetVarint32(pnt, (int *)&wrlen);
+ pnt += wrlen;
+ record_len = fstGetVarint32(pnt, (int *)&wrlen);
+ pnt += wrlen;
+
+ scratchpnt -= record_len;
+ memcpy(scratchpnt, pnt, record_len);
+
+ scratchpnt = fstCopyVarint32ToLeft(scratchpnt, record_len);
+ scratchpnt = fstCopyVarint32ToLeft(
+ scratchpnt, (time_delta << 1)); /* reserve | 1 case for future expansion */
+ }
+ }
+ } else {
+ wrlen = fstGetVarint32Length(vchg_mem + offs + 4); /* used to advance and determine wrlen */
+#ifndef FST_REMOVE_DUPLICATE_VC
+ memcpy(xc->curval_mem + vm4ip[0], vchg_mem + offs + 4 + wrlen, vm4ip[1]); /* checkpoint variable */
+#endif
+ while (offs) {
+ unsigned int idx;
+ char is_binary = 1;
+ unsigned char *pnt;
+ uint32_t time_delta;
+
+ next_offs = fstGetUint32(vchg_mem + offs);
+ offs += 4;
+
+ time_delta = fstGetVarint32(vchg_mem + offs, (int *)&wrlen);
+
+ pnt = vchg_mem + offs + wrlen;
+ offs = next_offs;
+
+ for (idx = 0; idx < vm4ip[1]; idx++) {
+ if ((pnt[idx] == '0') || (pnt[idx] == '1')) {
+ continue;
+ } else {
+ is_binary = 0;
+ break;
+ }
+ }
+
+ if (is_binary) {
+ unsigned char acc = 0;
+ /* new algorithm */
+ idx = ((vm4ip[1] + 7) & ~7);
+ switch (vm4ip[1] & 7) {
+ case 0:
+ do {
+ acc = (pnt[idx + 7 - 8] & 1) << 0; /* fallthrough */
+ case 7:
+ acc |= (pnt[idx + 6 - 8] & 1) << 1; /* fallthrough */
+ case 6:
+ acc |= (pnt[idx + 5 - 8] & 1) << 2; /* fallthrough */
+ case 5:
+ acc |= (pnt[idx + 4 - 8] & 1) << 3; /* fallthrough */
+ case 4:
+ acc |= (pnt[idx + 3 - 8] & 1) << 4; /* fallthrough */
+ case 3:
+ acc |= (pnt[idx + 2 - 8] & 1) << 5; /* fallthrough */
+ case 2:
+ acc |= (pnt[idx + 1 - 8] & 1) << 6; /* fallthrough */
+ case 1:
+ acc |= (pnt[idx + 0 - 8] & 1) << 7;
+ *(--scratchpnt) = acc;
+ idx -= 8;
+ } while (idx);
+ }
+
+ scratchpnt = fstCopyVarint32ToLeft(scratchpnt, (time_delta << 1));
+ } else {
+ scratchpnt -= vm4ip[1];
+ memcpy(scratchpnt, pnt, vm4ip[1]);
+
+ scratchpnt = fstCopyVarint32ToLeft(scratchpnt, (time_delta << 1) | 1);
+ }
+ }
+ }
+
+ wrlen = scratchpad + xc->vchg_siz - scratchpnt;
+ unc_memreq += wrlen;
+ if (wrlen > 32) {
+ unsigned long destlen = wrlen;
+ unsigned char *dmem;
+ unsigned int rc;
+
+ if (!xc->fastpack) {
+ if (wrlen <= packmemlen) {
+ dmem = packmem;
+ } else {
+ free(packmem);
+ dmem = packmem = (unsigned char *)malloc(compressBound(packmemlen = wrlen));
+ }
+
+ rc = compress2(dmem, &destlen, scratchpnt, wrlen, 4);
+ if (rc == Z_OK) {
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ PPvoid_t pv = JudyHSIns(&PJHSArray, dmem, destlen, NULL);
+ if (*pv) {
+ uint32_t pvi = (intptr_t)(*pv);
+ vm4ip[2] = -pvi;
+ } else {
+ *pv = (void *)(intptr_t)(i + 1);
+#endif
+ fpos += fstWriterVarint(f, wrlen);
+ fpos += destlen;
+ fstFwrite(dmem, destlen, 1, f);
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ }
+#endif
+ } else {
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL);
+ if (*pv) {
+ uint32_t pvi = (intptr_t)(*pv);
+ vm4ip[2] = -pvi;
+ } else {
+ *pv = (void *)(intptr_t)(i + 1);
+#endif
+ fpos += fstWriterVarint(f, 0);
+ fpos += wrlen;
+ fstFwrite(scratchpnt, wrlen, 1, f);
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ }
+#endif
+ }
+ } else {
+ /* this is extremely conservative: fastlz needs +5% for worst case, lz4 needs siz+(siz/255)+16 */
+ if (((wrlen * 2) + 2) <= packmemlen) {
+ dmem = packmem;
+ } else {
+ free(packmem);
+ dmem = packmem = (unsigned char *)malloc(packmemlen = (wrlen * 2) + 2);
+ }
+
+ rc = (xc->fourpack) ? LZ4_compress((char *)scratchpnt, (char *)dmem, wrlen)
+ : fastlz_compress(scratchpnt, wrlen, dmem);
+ if (rc < destlen) {
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ PPvoid_t pv = JudyHSIns(&PJHSArray, dmem, rc, NULL);
+ if (*pv) {
+ uint32_t pvi = (intptr_t)(*pv);
+ vm4ip[2] = -pvi;
+ } else {
+ *pv = (void *)(intptr_t)(i + 1);
+#endif
+ fpos += fstWriterVarint(f, wrlen);
+ fpos += rc;
+ fstFwrite(dmem, rc, 1, f);
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ }
+#endif
+ } else {
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL);
+ if (*pv) {
+ uint32_t pvi = (intptr_t)(*pv);
+ vm4ip[2] = -pvi;
+ } else {
+ *pv = (void *)(intptr_t)(i + 1);
+#endif
+ fpos += fstWriterVarint(f, 0);
+ fpos += wrlen;
+ fstFwrite(scratchpnt, wrlen, 1, f);
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ }
+#endif
+ }
+ }
+ } else {
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL);
+ if (*pv) {
+ uint32_t pvi = (intptr_t)(*pv);
+ vm4ip[2] = -pvi;
+ } else {
+ *pv = (void *)(intptr_t)(i + 1);
+#endif
+ fpos += fstWriterVarint(f, 0);
+ fpos += wrlen;
+ fstFwrite(scratchpnt, wrlen, 1, f);
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ }
+#endif
+ }
+
+ /* vm4ip[3] = 0; ...redundant with clearing below */
+#ifdef FST_DEBUG
+ cnt++;
+#endif
+ }
+ }
+
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+ JudyHSFreeArray(&PJHSArray, NULL);
+#endif
+
+ free(packmem);
+ packmem = NULL; /* packmemlen = 0; */ /* scan-build */
+
+ prevpos = 0;
+ zerocnt = 0;
+ free(scratchpad);
+ scratchpad = NULL;
+
+ indxpos = ftello(f);
+ xc->secnum++;
+
+#ifndef FST_DYNAMIC_ALIAS2_DISABLE
+ if (1) {
+ uint32_t prev_alias = 0;
+
+ for (i = 0; i < xc->maxhandle; i++) {
+ vm4ip = &(xc->valpos_mem[4 * i]);
+
+ if (vm4ip[2]) {
+ if (zerocnt) {
+ fpos += fstWriterVarint(f, (zerocnt << 1));
+ zerocnt = 0;
+ }
+
+ if (vm4ip[2] & 0x80000000) {
+ if (vm4ip[2] != prev_alias) {
+ fpos += fstWriterSVarint(f, (((int64_t)((int32_t)(prev_alias = vm4ip[2]))) << 1) | 1);
+ } else {
+ fpos += fstWriterSVarint(f, (0 << 1) | 1);
+ }
+ } else {
+ fpos += fstWriterSVarint(f, ((vm4ip[2] - prevpos) << 1) | 1);
+ prevpos = vm4ip[2];
+ }
+ vm4ip[2] = 0;
+ vm4ip[3] = 0; /* clear out tchn idx */
+ } else {
+ zerocnt++;
+ }
+ }
+ } else
+#endif
+ {
+ for (i = 0; i < xc->maxhandle; i++) {
+ vm4ip = &(xc->valpos_mem[4 * i]);
+
+ if (vm4ip[2]) {
+ if (zerocnt) {
+ fpos += fstWriterVarint(f, (zerocnt << 1));
+ zerocnt = 0;
+ }
+
+ if (vm4ip[2] & 0x80000000) {
+ fpos += fstWriterVarint(f, 0); /* signal, note that using a *signed* varint would be more efficient
+ than this byte escape! */
+ fpos += fstWriterVarint(f, (-(int32_t)vm4ip[2]));
+ } else {
+ fpos += fstWriterVarint(f, ((vm4ip[2] - prevpos) << 1) | 1);
+ prevpos = vm4ip[2];
+ }
+ vm4ip[2] = 0;
+ vm4ip[3] = 0; /* clear out tchn idx */
+ } else {
+ zerocnt++;
+ }
+ }
+ }
+
+ if (zerocnt) {
+ /* fpos += */ fstWriterVarint(f, (zerocnt << 1)); /* scan-build */
+ }
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "value chains: %d\n", cnt);
+#endif
+
+ xc->vchg_mem[0] = '!';
+ xc->vchg_siz = 1;
+
+ endpos = ftello(xc->handle);
+ fstWriterUint64(xc->handle, endpos - indxpos); /* write delta index position at very end of block */
+
+ /*emit time changes for block */
+ fflush(xc->tchn_handle);
+ tlen = ftello(xc->tchn_handle);
+ fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET);
+
+ errno = 0;
+ fstWriterMmapSanity(
+ tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(xc->tchn_handle), 0),
+ __FILE__, __LINE__, "tmem");
+ if (tmem) {
+ unsigned long destlen = tlen;
+ unsigned char *dmem = (unsigned char *)malloc(compressBound(destlen));
+ int rc = compress2(dmem, &destlen, tmem, tlen, 9);
+
+ if ((rc == Z_OK) && (((fst_off_t)destlen) < tlen)) {
+ fstFwrite(dmem, destlen, 1, xc->handle);
+ } else /* comparison between compressed / decompressed len tells if compressed */
+ {
+ fstFwrite(tmem, tlen, 1, xc->handle);
+ destlen = tlen;
+ }
+ free(dmem);
+ fstMunmap(tmem, tlen);
+ fstWriterUint64(xc->handle, tlen); /* uncompressed */
+ fstWriterUint64(xc->handle, destlen); /* compressed */
+ fstWriterUint64(xc->handle, xc->tchn_cnt); /* number of time items */
+ }
+
+ xc->tchn_cnt = xc->tchn_idx = 0;
+ fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET);
+ fstFtruncate(fileno(xc->tchn_handle), 0);
+
+ /* write block trailer */
+ endpos = ftello(xc->handle);
+ fstWriterFseeko(xc, xc->handle, xc->section_start, SEEK_SET);
+ fstWriterUint64(xc->handle, endpos - xc->section_start); /* write block length */
+ fstWriterFseeko(xc, xc->handle, 8, SEEK_CUR); /* skip begin time */
+ fstWriterUint64(xc->handle, xc->curtime); /* write end time for section */
+ fstWriterUint64(xc->handle, unc_memreq); /* amount of buffer memory required in reader for full traversal */
+ fflush(xc->handle);
+
+ fstWriterFseeko(xc, xc->handle, xc->section_start - 1, SEEK_SET); /* write out FST_BL_VCDATA over FST_BL_SKIP */
+
+#ifndef FST_DYNAMIC_ALIAS_DISABLE
+#ifndef FST_DYNAMIC_ALIAS2_DISABLE
+ fputc(FST_BL_VCDATA_DYN_ALIAS2, xc->handle);
+#else
+ fputc(FST_BL_VCDATA_DYN_ALIAS, xc->handle);
+#endif
+#else
+ fputc(FST_BL_VCDATA, xc->handle);
+#endif
+
+ fflush(xc->handle);
+
+ fstWriterFseeko(xc, xc->handle, endpos, SEEK_SET); /* seek to end of file */
+
+ xc2->section_header_truncpos = endpos; /* cache in case of need to truncate */
+ if (xc->dump_size_limit) {
+ if (endpos >= ((fst_off_t)xc->dump_size_limit)) {
+ xc2->skip_writing_section_hdr = 1;
+ xc2->size_limit_locked = 1;
+ xc2->is_initial_time = 1; /* to trick emit value and emit time change */
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "<< dump file size limit reached, stopping dumping >>\n");
+#endif
+ }
+ }
+
+ if (!xc2->skip_writing_section_hdr) {
+ fstWriterEmitSectionHeader(xc); /* emit next section header */
+ }
+ fflush(xc->handle);
+
+ xc->already_in_flush = 0;
+}
+
+#ifdef FST_WRITER_PARALLEL
+static void *fstWriterFlushContextPrivate1(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ struct fstWriterContext *xc_parent;
+
+ pthread_mutex_lock(&(xc->xc_parent->mutex));
+ fstWriterFlushContextPrivate2(xc);
+
+#ifdef FST_REMOVE_DUPLICATE_VC
+ free(xc->curval_mem);
+#endif
+ free(xc->valpos_mem);
+ free(xc->vchg_mem);
+ tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam);
+ xc_parent = xc->xc_parent;
+ free(xc);
+
+ xc_parent->in_pthread = 0;
+ pthread_mutex_unlock(&(xc_parent->mutex));
+
+ return (NULL);
+}
+
+static void fstWriterFlushContextPrivate(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc->parallel_enabled) {
+ struct fstWriterContext *xc2 = (struct fstWriterContext *)malloc(sizeof(struct fstWriterContext));
+ unsigned int i;
+
+ pthread_mutex_lock(&xc->mutex);
+ pthread_mutex_unlock(&xc->mutex);
+
+ xc->xc_parent = xc;
+ memcpy(xc2, xc, sizeof(struct fstWriterContext));
+
+ xc2->valpos_mem = (uint32_t *)malloc(xc->maxhandle * 4 * sizeof(uint32_t));
+ memcpy(xc2->valpos_mem, xc->valpos_mem, xc->maxhandle * 4 * sizeof(uint32_t));
+
+ /* curval mem is updated in the thread */
+#ifdef FST_REMOVE_DUPLICATE_VC
+ xc2->curval_mem = (unsigned char *)malloc(xc->maxvalpos);
+ memcpy(xc2->curval_mem, xc->curval_mem, xc->maxvalpos);
+#endif
+
+ xc->vchg_mem = (unsigned char *)malloc(xc->vchg_alloc_siz);
+ xc->vchg_mem[0] = '!';
+ xc->vchg_siz = 1;
+
+ for (i = 0; i < xc->maxhandle; i++) {
+ uint32_t *vm4ip = &(xc->valpos_mem[4 * i]);
+ vm4ip[2] = 0; /* zero out offset val */
+ vm4ip[3] = 0; /* zero out last time change val */
+ }
+
+ xc->tchn_cnt = xc->tchn_idx = 0;
+ xc->tchn_handle = tmpfile_open(&xc->tchn_handle_nam); /* child thread will deallocate file/name */
+ fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET);
+ fstFtruncate(fileno(xc->tchn_handle), 0);
+
+ xc->section_header_only = 0;
+ xc->secnum++;
+
+ while (xc->in_pthread) {
+ pthread_mutex_lock(&xc->mutex);
+ pthread_mutex_unlock(&xc->mutex);
+ };
+
+ pthread_mutex_lock(&xc->mutex);
+ xc->in_pthread = 1;
+ pthread_mutex_unlock(&xc->mutex);
+
+ pthread_create(&xc->thread, &xc->thread_attr, fstWriterFlushContextPrivate1, xc2);
+ } else {
+ if (xc->parallel_was_enabled) /* conservatively block */
+ {
+ pthread_mutex_lock(&xc->mutex);
+ pthread_mutex_unlock(&xc->mutex);
+ }
+
+ xc->xc_parent = xc;
+ fstWriterFlushContextPrivate2(xc);
+ }
+}
+#endif
+
+/*
+ * queues up a flush context operation
+ */
+void fstWriterFlushContext(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ if (xc->tchn_idx > 1) {
+ xc->flush_context_pending = 1;
+ }
+ }
+}
+
+/*
+ * close out FST file
+ */
+void fstWriterClose(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+#ifdef FST_WRITER_PARALLEL
+ if (xc) {
+ pthread_mutex_lock(&xc->mutex);
+ pthread_mutex_unlock(&xc->mutex);
+ }
+#endif
+
+ if (xc && !xc->already_in_close && !xc->already_in_flush) {
+ unsigned char *tmem = NULL;
+ fst_off_t fixup_offs, tlen, hlen;
+
+ xc->already_in_close = 1; /* never need to zero this out as it is freed at bottom */
+
+ if (xc->section_header_only && xc->section_header_truncpos && (xc->vchg_siz <= 1) && (!xc->is_initial_time)) {
+ fstFtruncate(fileno(xc->handle), xc->section_header_truncpos);
+ fstWriterFseeko(xc, xc->handle, xc->section_header_truncpos, SEEK_SET);
+ xc->section_header_only = 0;
+ } else {
+ xc->skip_writing_section_hdr = 1;
+ if (!xc->size_limit_locked) {
+ if (FST_UNLIKELY(xc->is_initial_time)) /* simulation time never advanced so mock up the changes as time
+ zero ones */
+ {
+ fstHandle dupe_idx;
+
+ fstWriterEmitTimeChange(xc, 0); /* emit some time change just to have one */
+ for (dupe_idx = 0; dupe_idx < xc->maxhandle; dupe_idx++) /* now clone the values */
+ {
+ fstWriterEmitValueChange(xc, dupe_idx + 1, xc->curval_mem + xc->valpos_mem[4 * dupe_idx]);
+ }
+ }
+ fstWriterFlushContextPrivate(xc);
+#ifdef FST_WRITER_PARALLEL
+ pthread_mutex_lock(&xc->mutex);
+ pthread_mutex_unlock(&xc->mutex);
+
+ while (xc->in_pthread) {
+ pthread_mutex_lock(&xc->mutex);
+ pthread_mutex_unlock(&xc->mutex);
+ };
+#endif
+ }
+ }
+ fstDestroyMmaps(xc, 1);
+ if (xc->outval_mem) {
+ free(xc->outval_mem);
+ xc->outval_mem = NULL;
+ xc->outval_alloc_siz = 0;
+ }
+
+ /* write out geom section */
+ fflush(xc->geom_handle);
+ tlen = ftello(xc->geom_handle);
+ errno = 0;
+ if (tlen) {
+ fstWriterMmapSanity(tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ | PROT_WRITE, MAP_SHARED,
+ fileno(xc->geom_handle), 0),
+ __FILE__, __LINE__, "tmem");
+ }
+
+ if (tmem) {
+ unsigned long destlen = tlen;
+ unsigned char *dmem = (unsigned char *)malloc(compressBound(destlen));
+ int rc = compress2(dmem, &destlen, tmem, tlen, 9);
+
+ if ((rc != Z_OK) || (((fst_off_t)destlen) > tlen)) {
+ destlen = tlen;
+ }
+
+ fixup_offs = ftello(xc->handle);
+ fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
+ fstWriterUint64(xc->handle, destlen + 24); /* section length */
+ fstWriterUint64(xc->handle, tlen); /* uncompressed */
+ /* compressed len is section length - 24 */
+ fstWriterUint64(xc->handle, xc->maxhandle); /* maxhandle */
+ fstFwrite((((fst_off_t)destlen) != tlen) ? dmem : tmem, destlen, 1, xc->handle);
+ fflush(xc->handle);
+
+ fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET);
+ fputc(FST_BL_GEOM, xc->handle); /* actual tag */
+
+ fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
+ fflush(xc->handle);
+
+ free(dmem);
+ fstMunmap(tmem, tlen);
+ }
+
+ if (xc->num_blackouts) {
+ uint64_t cur_bl = 0;
+ fst_off_t bpos, eos;
+ uint32_t i;
+
+ fixup_offs = ftello(xc->handle);
+ fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
+ bpos = fixup_offs + 1;
+ fstWriterUint64(xc->handle, 0); /* section length */
+ fstWriterVarint(xc->handle, xc->num_blackouts);
+
+ for (i = 0; i < xc->num_blackouts; i++) {
+ fputc(xc->blackout_head->active, xc->handle);
+ fstWriterVarint(xc->handle, xc->blackout_head->tim - cur_bl);
+ cur_bl = xc->blackout_head->tim;
+ xc->blackout_curr = xc->blackout_head->next;
+ free(xc->blackout_head);
+ xc->blackout_head = xc->blackout_curr;
+ }
+
+ eos = ftello(xc->handle);
+ fstWriterFseeko(xc, xc->handle, bpos, SEEK_SET);
+ fstWriterUint64(xc->handle, eos - bpos);
+ fflush(xc->handle);
+
+ fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET);
+ fputc(FST_BL_BLACKOUT, xc->handle); /* actual tag */
+
+ fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
+ fflush(xc->handle);
+ }
+
+ if (xc->compress_hier) {
+ fst_off_t hl, eos;
+ gzFile zhandle;
+ int zfd;
+ int fourpack_duo = 0;
+#ifndef __MINGW32__
+ char *fnam = (char *)malloc(strlen(xc->filename) + 5 + 1);
+#endif
+
+ fixup_offs = ftello(xc->handle);
+ fputc(FST_BL_SKIP, xc->handle); /* temporary tag */
+ hlen = ftello(xc->handle);
+ fstWriterUint64(xc->handle, 0); /* section length */
+ fstWriterUint64(xc->handle, xc->hier_file_len); /* uncompressed length */
+
+ if (!xc->fourpack) {
+ unsigned char *mem = (unsigned char *)malloc(FST_GZIO_LEN);
+ zfd = dup(fileno(xc->handle));
+ fflush(xc->handle);
+ zhandle = gzdopen(zfd, "wb4");
+ if (zhandle) {
+ fstWriterFseeko(xc, xc->hier_handle, 0, SEEK_SET);
+ for (hl = 0; hl < xc->hier_file_len; hl += FST_GZIO_LEN) {
+ unsigned len =
+ ((xc->hier_file_len - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (xc->hier_file_len - hl);
+ fstFread(mem, len, 1, xc->hier_handle);
+ gzwrite(zhandle, mem, len);
+ }
+ gzclose(zhandle);
+ } else {
+ close(zfd);
+ }
+ free(mem);
+ } else {
+ int lz4_maxlen;
+ unsigned char *mem;
+ unsigned char *hmem = NULL;
+ int packed_len;
+
+ fflush(xc->handle);
+
+ lz4_maxlen = LZ4_compressBound(xc->hier_file_len);
+ mem = (unsigned char *)malloc(lz4_maxlen);
+ errno = 0;
+ if (xc->hier_file_len) {
+ fstWriterMmapSanity(hmem = (unsigned char *)fstMmap(NULL, xc->hier_file_len, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fileno(xc->hier_handle), 0),
+ __FILE__, __LINE__, "hmem");
+ }
+ packed_len = LZ4_compress((char *)hmem, (char *)mem, xc->hier_file_len);
+ fstMunmap(hmem, xc->hier_file_len);
+
+ fourpack_duo =
+ (!xc->repack_on_close) &&
+ (xc->hier_file_len > FST_HDR_FOURPACK_DUO_SIZE); /* double pack when hierarchy is large */
+
+ if (fourpack_duo) /* double packing with LZ4 is faster than gzip */
+ {
+ unsigned char *mem_duo;
+ int lz4_maxlen_duo;
+ int packed_len_duo;
+
+ lz4_maxlen_duo = LZ4_compressBound(packed_len);
+ mem_duo = (unsigned char *)malloc(lz4_maxlen_duo);
+ packed_len_duo = LZ4_compress((char *)mem, (char *)mem_duo, packed_len);
+
+ fstWriterVarint(xc->handle, packed_len); /* 1st round compressed length */
+ fstFwrite(mem_duo, packed_len_duo, 1, xc->handle);
+ free(mem_duo);
+ } else {
+ fstFwrite(mem, packed_len, 1, xc->handle);
+ }
+
+ free(mem);
+ }
+
+ fstWriterFseeko(xc, xc->handle, 0, SEEK_END);
+ eos = ftello(xc->handle);
+ fstWriterFseeko(xc, xc->handle, hlen, SEEK_SET);
+ fstWriterUint64(xc->handle, eos - hlen);
+ fflush(xc->handle);
+
+ fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET);
+ fputc(xc->fourpack ? (fourpack_duo ? FST_BL_HIER_LZ4DUO : FST_BL_HIER_LZ4) : FST_BL_HIER,
+ xc->handle); /* actual tag now also == compression type */
+
+ fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */
+ fflush(xc->handle);
+
+#ifndef __MINGW32__
+ sprintf(fnam, "%s.hier", xc->filename);
+ unlink(fnam);
+ free(fnam);
+#endif
+ }
+
+ /* finalize out header */
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_START_TIME, SEEK_SET);
+ fstWriterUint64(xc->handle, xc->firsttime);
+ fstWriterUint64(xc->handle, xc->curtime);
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_NUM_SCOPES, SEEK_SET);
+ fstWriterUint64(xc->handle, xc->numscopes);
+ fstWriterUint64(xc->handle, xc->numsigs);
+ fstWriterUint64(xc->handle, xc->maxhandle);
+ fstWriterUint64(xc->handle, xc->secnum);
+ fflush(xc->handle);
+
+ tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam);
+ free(xc->vchg_mem);
+ xc->vchg_mem = NULL;
+ tmpfile_close(&xc->curval_handle, &xc->curval_handle_nam);
+ tmpfile_close(&xc->valpos_handle, &xc->valpos_handle_nam);
+ tmpfile_close(&xc->geom_handle, &xc->geom_handle_nam);
+ if (xc->hier_handle) {
+ fclose(xc->hier_handle);
+ xc->hier_handle = NULL;
+ }
+ if (xc->handle) {
+ if (xc->repack_on_close) {
+ FILE *fp;
+ fst_off_t offpnt, uclen;
+ int flen = strlen(xc->filename);
+ char *hf = (char *)calloc(1, flen + 5);
+
+ strcpy(hf, xc->filename);
+ strcpy(hf + flen, ".pak");
+ fp = fopen(hf, "wb");
+
+ if (fp) {
+ gzFile dsth;
+ int zfd;
+ char gz_membuf[FST_GZIO_LEN];
+
+ fstWriterFseeko(xc, xc->handle, 0, SEEK_END);
+ uclen = ftello(xc->handle);
+
+ fputc(FST_BL_ZWRAPPER, fp);
+ fstWriterUint64(fp, 0);
+ fstWriterUint64(fp, uclen);
+ fflush(fp);
+
+ fstWriterFseeko(xc, xc->handle, 0, SEEK_SET);
+ zfd = dup(fileno(fp));
+ dsth = gzdopen(zfd, "wb4");
+ if (dsth) {
+ for (offpnt = 0; offpnt < uclen; offpnt += FST_GZIO_LEN) {
+ size_t this_len = ((uclen - offpnt) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - offpnt);
+ fstFread(gz_membuf, this_len, 1, xc->handle);
+ gzwrite(dsth, gz_membuf, this_len);
+ }
+ gzclose(dsth);
+ } else {
+ close(zfd);
+ }
+ fstWriterFseeko(xc, fp, 0, SEEK_END);
+ offpnt = ftello(fp);
+ fstWriterFseeko(xc, fp, 1, SEEK_SET);
+ fstWriterUint64(fp, offpnt - 1);
+ fclose(fp);
+ fclose(xc->handle);
+ xc->handle = NULL;
+
+ unlink(xc->filename);
+ rename(hf, xc->filename);
+ } else {
+ xc->repack_on_close = 0;
+ fclose(xc->handle);
+ xc->handle = NULL;
+ }
+
+ free(hf);
+ } else {
+ fclose(xc->handle);
+ xc->handle = NULL;
+ }
+ }
+
+#ifdef __MINGW32__
+ {
+ int flen = strlen(xc->filename);
+ char *hf = (char *)calloc(1, flen + 6);
+ strcpy(hf, xc->filename);
+
+ if (xc->compress_hier) {
+ strcpy(hf + flen, ".hier");
+ unlink(hf); /* no longer needed as a section now exists for this */
+ }
+
+ free(hf);
+ }
+#endif
+
+#ifdef FST_WRITER_PARALLEL
+ pthread_mutex_destroy(&xc->mutex);
+ pthread_attr_destroy(&xc->thread_attr);
+#endif
+
+ if (xc->path_array) {
+#ifndef _WAVE_HAVE_JUDY
+ const uint32_t hashmask = FST_PATH_HASHMASK;
+#endif
+ JudyHSFreeArray(&(xc->path_array), NULL);
+ }
+
+ free(xc->filename);
+ xc->filename = NULL;
+ free(xc);
+ }
+}
+
+/*
+ * functions to set miscellaneous header/block information
+ */
+void fstWriterSetDate(void *ctx, const char *dat)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ char s[FST_HDR_DATE_SIZE];
+ fst_off_t fpos = ftello(xc->handle);
+ int len = strlen(dat);
+
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_DATE, SEEK_SET);
+ memset(s, 0, FST_HDR_DATE_SIZE);
+ memcpy(s, dat, (len < FST_HDR_DATE_SIZE) ? len : FST_HDR_DATE_SIZE);
+ fstFwrite(s, FST_HDR_DATE_SIZE, 1, xc->handle);
+ fflush(xc->handle);
+ fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET);
+ }
+}
+
+void fstWriterSetVersion(void *ctx, const char *vers)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc && vers) {
+ char s[FST_HDR_SIM_VERSION_SIZE];
+ fst_off_t fpos = ftello(xc->handle);
+ int len = strlen(vers);
+
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_SIM_VERSION, SEEK_SET);
+ memset(s, 0, FST_HDR_SIM_VERSION_SIZE);
+ memcpy(s, vers, (len < FST_HDR_SIM_VERSION_SIZE) ? len : FST_HDR_SIM_VERSION_SIZE);
+ fstFwrite(s, FST_HDR_SIM_VERSION_SIZE, 1, xc->handle);
+ fflush(xc->handle);
+ fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET);
+ }
+}
+
+void fstWriterSetFileType(void *ctx, enum fstFileType filetype)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ if (/*(filetype >= FST_FT_MIN) &&*/ (filetype <= FST_FT_MAX)) {
+ fst_off_t fpos = ftello(xc->handle);
+
+ xc->filetype = filetype;
+
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_FILETYPE, SEEK_SET);
+ fputc(xc->filetype, xc->handle);
+ fflush(xc->handle);
+ fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET);
+ }
+ }
+}
+
+static void fstWriterSetAttrDoubleArgGeneric(void *ctx, int typ, uint64_t arg1, uint64_t arg2)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ unsigned char buf[11]; /* ceil(64/7) = 10 + null term */
+ unsigned char *pnt = fstCopyVarint64ToRight(buf, arg1);
+ if (arg1) {
+ *pnt = 0; /* this converts any *nonzero* arg1 when made a varint into a null-term string */
+ }
+
+ fstWriterSetAttrBegin(xc, FST_AT_MISC, typ, (char *)buf, arg2);
+ }
+}
+
+static void fstWriterSetAttrGeneric(void *ctx, const char *comm, int typ, uint64_t arg)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc && comm) {
+ char *s = strdup(comm);
+ char *sf = s;
+
+ while (*s) {
+ if ((*s == '\n') || (*s == '\r'))
+ *s = ' ';
+ s++;
+ }
+
+ fstWriterSetAttrBegin(xc, FST_AT_MISC, typ, sf, arg);
+ free(sf);
+ }
+}
+
+static void fstWriterSetSourceStem_2(void *ctx, const char *path, unsigned int line, unsigned int use_realpath, int typ)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc && path && path[0]) {
+ uint64_t sidx = 0;
+ int slen = strlen(path);
+#ifndef _WAVE_HAVE_JUDY
+ const uint32_t hashmask = FST_PATH_HASHMASK;
+ const unsigned char *path2 = (const unsigned char *)path;
+ PPvoid_t pv;
+#else
+ char *path2 = (char *)alloca(slen + 1); /* judy lacks const qualifier in its JudyHSIns definition */
+ PPvoid_t pv;
+ strcpy(path2, path);
+#endif
+
+ pv = JudyHSIns(&(xc->path_array), path2, slen, NULL);
+ if (*pv) {
+ sidx = (intptr_t)(*pv);
+ } else {
+ char *rp = NULL;
+
+ sidx = ++xc->path_array_count;
+ *pv = (void *)(intptr_t)(xc->path_array_count);
+
+ if (use_realpath) {
+ rp = fstRealpath(
+#ifndef _WAVE_HAVE_JUDY
+ (const char *)
+#endif
+ path2,
+ NULL);
+ }
+
+ fstWriterSetAttrGeneric(xc,
+ rp ? rp :
+#ifndef _WAVE_HAVE_JUDY
+ (const char *)
+#endif
+ path2,
+ FST_MT_PATHNAME, sidx);
+
+ if (rp) {
+ free(rp);
+ }
+ }
+
+ fstWriterSetAttrDoubleArgGeneric(xc, typ, sidx, line);
+ }
+}
+
+void fstWriterSetSourceStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath)
+{
+ fstWriterSetSourceStem_2(ctx, path, line, use_realpath, FST_MT_SOURCESTEM);
+}
+
+void fstWriterSetSourceInstantiationStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath)
+{
+ fstWriterSetSourceStem_2(ctx, path, line, use_realpath, FST_MT_SOURCEISTEM);
+}
+
+void fstWriterSetComment(void *ctx, const char *comm) { fstWriterSetAttrGeneric(ctx, comm, FST_MT_COMMENT, 0); }
+
+void fstWriterSetValueList(void *ctx, const char *vl) { fstWriterSetAttrGeneric(ctx, vl, FST_MT_VALUELIST, 0); }
+
+void fstWriterSetEnvVar(void *ctx, const char *envvar) { fstWriterSetAttrGeneric(ctx, envvar, FST_MT_ENVVAR, 0); }
+
+void fstWriterSetTimescale(void *ctx, int ts)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ fst_off_t fpos = ftello(xc->handle);
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_TIMESCALE, SEEK_SET);
+ fputc(ts & 255, xc->handle);
+ fflush(xc->handle);
+ fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET);
+ }
+}
+
+void fstWriterSetTimescaleFromString(void *ctx, const char *s)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc && s) {
+ int mat = 0;
+ int seconds_exp = -9;
+ int tv = atoi(s);
+ const char *pnt = s;
+
+ while (*pnt) {
+ switch (*pnt) {
+ case 'm':
+ seconds_exp = -3;
+ mat = 1;
+ break;
+ case 'u':
+ seconds_exp = -6;
+ mat = 1;
+ break;
+ case 'n':
+ seconds_exp = -9;
+ mat = 1;
+ break;
+ case 'p':
+ seconds_exp = -12;
+ mat = 1;
+ break;
+ case 'f':
+ seconds_exp = -15;
+ mat = 1;
+ break;
+ case 'a':
+ seconds_exp = -18;
+ mat = 1;
+ break;
+ case 'z':
+ seconds_exp = -21;
+ mat = 1;
+ break;
+ case 's':
+ seconds_exp = 0;
+ mat = 1;
+ break;
+ default:
+ break;
+ }
+
+ if (mat)
+ break;
+ pnt++;
+ }
+
+ if (tv == 10) {
+ seconds_exp++;
+ } else if (tv == 100) {
+ seconds_exp += 2;
+ }
+
+ fstWriterSetTimescale(ctx, seconds_exp);
+ }
+}
+
+void fstWriterSetTimezero(void *ctx, int64_t tim)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ fst_off_t fpos = ftello(xc->handle);
+ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_TIMEZERO, SEEK_SET);
+ fstWriterUint64(xc->handle, (xc->timezero = tim));
+ fflush(xc->handle);
+ fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET);
+ }
+}
+
+void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ xc->fastpack = (typ != FST_WR_PT_ZLIB);
+ xc->fourpack = (typ == FST_WR_PT_LZ4);
+ }
+}
+
+void fstWriterSetRepackOnClose(void *ctx, int enable)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ xc->repack_on_close = (enable != 0);
+ }
+}
+
+void fstWriterSetParallelMode(void *ctx, int enable)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ xc->parallel_was_enabled |= xc->parallel_enabled; /* make sticky */
+ xc->parallel_enabled = (enable != 0);
+#ifndef FST_WRITER_PARALLEL
+ if (xc->parallel_enabled) {
+ fprintf(stderr, FST_APIMESS
+ "fstWriterSetParallelMode(), FST_WRITER_PARALLEL not enabled during compile, exiting.\n");
+ exit(255);
+ }
+#endif
+ }
+}
+
+void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ xc->dump_size_limit = numbytes;
+ }
+}
+
+int fstWriterGetDumpSizeLimitReached(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ return (xc->size_limit_locked != 0);
+ }
+
+ return (0);
+}
+
+int fstWriterGetFseekFailed(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc) {
+ return (xc->fseek_failed != 0);
+ }
+
+ return (0);
+}
+
+/*
+ * writer attr/scope/var creation:
+ * fstWriterCreateVar2() is used to dump VHDL or other languages, but the
+ * underlying variable needs to map to Verilog/SV via the proper fstVarType vt
+ */
+fstHandle fstWriterCreateVar2(void *ctx, enum fstVarType vt, enum fstVarDir vd, uint32_t len, const char *nam,
+ fstHandle aliasHandle, const char *type, enum fstSupplementalVarType svt,
+ enum fstSupplementalDataType sdt)
+{
+ fstWriterSetAttrGeneric(ctx, type ? type : "", FST_MT_SUPVAR,
+ (svt << FST_SDT_SVT_SHIFT_COUNT) | (sdt & FST_SDT_ABS_MAX));
+ return (fstWriterCreateVar(ctx, vt, vd, len, nam, aliasHandle));
+}
+
+fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd, uint32_t len, const char *nam,
+ fstHandle aliasHandle)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ unsigned int i;
+ int nlen, is_real;
+
+ if (xc && nam) {
+ if (xc->valpos_mem) {
+ fstDestroyMmaps(xc, 0);
+ }
+
+ fputc(vt, xc->hier_handle);
+ fputc(vd, xc->hier_handle);
+ nlen = strlen(nam);
+ fstFwrite(nam, nlen, 1, xc->hier_handle);
+ fputc(0, xc->hier_handle);
+ xc->hier_file_len += (nlen + 3);
+
+ if ((vt == FST_VT_VCD_REAL) || (vt == FST_VT_VCD_REAL_PARAMETER) || (vt == FST_VT_VCD_REALTIME) ||
+ (vt == FST_VT_SV_SHORTREAL)) {
+ is_real = 1;
+ len = 8; /* recast number of bytes to that of what a double is */
+ } else {
+ is_real = 0;
+ if (vt == FST_VT_GEN_STRING) {
+ len = 0;
+ }
+ }
+
+ xc->hier_file_len += fstWriterVarint(xc->hier_handle, len);
+
+ if (aliasHandle > xc->maxhandle)
+ aliasHandle = 0;
+ xc->hier_file_len += fstWriterVarint(xc->hier_handle, aliasHandle);
+ xc->numsigs++;
+ if (xc->numsigs == xc->next_huge_break) {
+ if (xc->fst_break_size < xc->fst_huge_break_size) {
+ xc->next_huge_break += FST_ACTIVATE_HUGE_INC;
+ xc->fst_break_size += xc->fst_orig_break_size;
+ xc->fst_break_add_size += xc->fst_orig_break_add_size;
+
+ xc->vchg_alloc_siz = xc->fst_break_size + xc->fst_break_add_size;
+ if (xc->vchg_mem) {
+ xc->vchg_mem = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz);
+ }
+ }
+ }
+
+ if (!aliasHandle) {
+ uint32_t zero = 0;
+
+ if (len) {
+ fstWriterVarint(xc->geom_handle, !is_real ? len : 0); /* geom section encodes reals as zero byte */
+ } else {
+ fstWriterVarint(xc->geom_handle, 0xFFFFFFFF); /* geom section encodes zero len as 32b -1 */
+ }
+
+ fstFwrite(&xc->maxvalpos, sizeof(uint32_t), 1, xc->valpos_handle);
+ fstFwrite(&len, sizeof(uint32_t), 1, xc->valpos_handle);
+ fstFwrite(&zero, sizeof(uint32_t), 1, xc->valpos_handle);
+ fstFwrite(&zero, sizeof(uint32_t), 1, xc->valpos_handle);
+
+ if (!is_real) {
+ for (i = 0; i < len; i++) {
+ fputc('x', xc->curval_handle);
+ }
+ } else {
+ fstFwrite(&xc->nan, 8, 1, xc->curval_handle); /* initialize doubles to NaN rather than x */
+ }
+
+ xc->maxvalpos += len;
+ xc->maxhandle++;
+ return (xc->maxhandle);
+ } else {
+ return (aliasHandle);
+ }
+ }
+
+ return (0);
+}
+
+void fstWriterSetScope(void *ctx, enum fstScopeType scopetype, const char *scopename, const char *scopecomp)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc) {
+ fputc(FST_ST_VCD_SCOPE, xc->hier_handle);
+ if (/*(scopetype < FST_ST_VCD_MODULE) ||*/ (scopetype > FST_ST_MAX)) {
+ scopetype = FST_ST_VCD_MODULE;
+ }
+ fputc(scopetype, xc->hier_handle);
+ fprintf(xc->hier_handle, "%s%c%s%c", scopename ? scopename : "", 0, scopecomp ? scopecomp : "", 0);
+
+ if (scopename) {
+ xc->hier_file_len += strlen(scopename);
+ }
+ if (scopecomp) {
+ xc->hier_file_len += strlen(scopecomp);
+ }
+
+ xc->hier_file_len += 4; /* FST_ST_VCD_SCOPE + scopetype + two string terminating zeros */
+ xc->numscopes++;
+ }
+}
+
+void fstWriterSetUpscope(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc) {
+ fputc(FST_ST_VCD_UPSCOPE, xc->hier_handle);
+ xc->hier_file_len++;
+ }
+}
+
+void fstWriterSetAttrBegin(void *ctx, enum fstAttrType attrtype, int subtype, const char *attrname, uint64_t arg)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc) {
+ fputc(FST_ST_GEN_ATTRBEGIN, xc->hier_handle);
+ if (/*(attrtype < FST_AT_MISC) ||*/ (attrtype > FST_AT_MAX)) {
+ attrtype = FST_AT_MISC;
+ subtype = FST_MT_UNKNOWN;
+ }
+ fputc(attrtype, xc->hier_handle);
+
+ switch (attrtype) {
+ case FST_AT_ARRAY:
+ if ((subtype < FST_AR_NONE) || (subtype > FST_AR_MAX))
+ subtype = FST_AR_NONE;
+ break;
+ case FST_AT_ENUM:
+ if ((subtype < FST_EV_SV_INTEGER) || (subtype > FST_EV_MAX))
+ subtype = FST_EV_SV_INTEGER;
+ break;
+ case FST_AT_PACK:
+ if ((subtype < FST_PT_NONE) || (subtype > FST_PT_MAX))
+ subtype = FST_PT_NONE;
+ break;
+
+ case FST_AT_MISC:
+ default:
+ break;
+ }
+
+ fputc(subtype, xc->hier_handle);
+ fprintf(xc->hier_handle, "%s%c", attrname ? attrname : "", 0);
+
+ if (attrname) {
+ xc->hier_file_len += strlen(attrname);
+ }
+
+ xc->hier_file_len += 4; /* FST_ST_GEN_ATTRBEGIN + type + subtype + string terminating zero */
+ xc->hier_file_len += fstWriterVarint(xc->hier_handle, arg);
+ }
+}
+
+void fstWriterSetAttrEnd(void *ctx)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc) {
+ fputc(FST_ST_GEN_ATTREND, xc->hier_handle);
+ xc->hier_file_len++;
+ }
+}
+
+fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t elem_count, unsigned int min_valbits,
+ const char **literal_arr, const char **val_arr)
+{
+ fstEnumHandle handle = 0;
+ unsigned int *literal_lens = NULL;
+ unsigned int *val_lens = NULL;
+ int lit_len_tot = 0;
+ int val_len_tot = 0;
+ int name_len;
+ char elem_count_buf[16];
+ int elem_count_len;
+ int total_len;
+ int pos = 0;
+ char *attr_str = NULL;
+
+ if (ctx && name && literal_arr && val_arr && (elem_count != 0)) {
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ uint32_t i;
+
+ name_len = strlen(name);
+ elem_count_len = sprintf(elem_count_buf, "%" PRIu32, elem_count);
+
+ literal_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int));
+ val_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int));
+
+ for (i = 0; i < elem_count; i++) {
+ literal_lens[i] = strlen(literal_arr[i]);
+ lit_len_tot += fstUtilityBinToEscConvertedLen((unsigned char *)literal_arr[i], literal_lens[i]);
+
+ val_lens[i] = strlen(val_arr[i]);
+ val_len_tot += fstUtilityBinToEscConvertedLen((unsigned char *)val_arr[i], val_lens[i]);
+
+ if (min_valbits > 0) {
+ if (val_lens[i] < min_valbits) {
+ val_len_tot += (min_valbits - val_lens[i]); /* additional converted len is same for '0' character */
+ }
+ }
+ }
+
+ total_len = name_len + 1 + elem_count_len + 1 + lit_len_tot + elem_count + val_len_tot + elem_count;
+
+ attr_str = (char *)malloc(total_len);
+ pos = 0;
+
+ memcpy(attr_str + pos, name, name_len);
+ pos += name_len;
+ attr_str[pos++] = ' ';
+
+ memcpy(attr_str + pos, elem_count_buf, elem_count_len);
+ pos += elem_count_len;
+ attr_str[pos++] = ' ';
+
+ for (i = 0; i < elem_count; i++) {
+ pos += fstUtilityBinToEsc((unsigned char *)attr_str + pos, (unsigned char *)literal_arr[i],
+ literal_lens[i]);
+ attr_str[pos++] = ' ';
+ }
+
+ for (i = 0; i < elem_count; i++) {
+ if (min_valbits > 0) {
+ if (val_lens[i] < min_valbits) {
+ memset(attr_str + pos, '0', min_valbits - val_lens[i]);
+ pos += (min_valbits - val_lens[i]);
+ }
+ }
+
+ pos += fstUtilityBinToEsc((unsigned char *)attr_str + pos, (unsigned char *)val_arr[i], val_lens[i]);
+ attr_str[pos++] = ' ';
+ }
+
+ attr_str[pos - 1] = 0;
+
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "fstWriterCreateEnumTable() total_len: %d, pos: %d\n", total_len, pos);
+ fprintf(stderr, FST_APIMESS "*%s*\n", attr_str);
+#endif
+
+ fstWriterSetAttrBegin(xc, FST_AT_MISC, FST_MT_ENUMTABLE, attr_str, handle = ++xc->max_enumhandle);
+
+ free(attr_str);
+ free(val_lens);
+ free(literal_lens);
+ }
+
+ return (handle);
+}
+
+void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (xc && handle) {
+ fstWriterSetAttrBegin(xc, FST_AT_MISC, FST_MT_ENUMTABLE, NULL, handle);
+ }
+}
+
+/*
+ * value and time change emission
+ */
+void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ const unsigned char *buf = (const unsigned char *)val;
+ uint32_t offs;
+ int len;
+
+ if (FST_LIKELY((xc) && (handle <= xc->maxhandle))) {
+ uint32_t fpos;
+ uint32_t *vm4ip;
+
+ if (FST_UNLIKELY(!xc->valpos_mem)) {
+ xc->vc_emitted = 1;
+ fstWriterCreateMmaps(xc);
+ }
+
+ handle--; /* move starting at 1 index to starting at 0 */
+ vm4ip = &(xc->valpos_mem[4 * handle]);
+
+ len = vm4ip[1];
+ if (FST_LIKELY(len)) /* len of zero = variable length, use fstWriterEmitVariableLengthValueChange */
+ {
+ if (FST_LIKELY(!xc->is_initial_time)) {
+ fpos = xc->vchg_siz;
+
+ if (FST_UNLIKELY((fpos + len + 10) > xc->vchg_alloc_siz)) {
+ xc->vchg_alloc_siz +=
+ (xc->fst_break_add_size +
+ len); /* +len added in the case of extremely long vectors and small break add sizes */
+ xc->vchg_mem = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz);
+ if (FST_UNLIKELY(!xc->vchg_mem)) {
+ fprintf(stderr, FST_APIMESS "Could not realloc() in fstWriterEmitValueChange, exiting.\n");
+ exit(255);
+ }
+ }
+#ifdef FST_REMOVE_DUPLICATE_VC
+ offs = vm4ip[0];
+
+ if (len != 1) {
+ if ((vm4ip[3] == xc->tchn_idx) && (vm4ip[2])) {
+ unsigned char *old_value = xc->vchg_mem + vm4ip[2] + 4; /* the +4 skips old vm4ip[2] value */
+ while (*(old_value++) & 0x80) { /* skips over varint encoded "xc->tchn_idx - vm4ip[3]" */
+ }
+ memcpy(old_value, buf, len); /* overlay new value */
+
+ memcpy(xc->curval_mem + offs, buf, len);
+ return;
+ } else {
+ if (!memcmp(xc->curval_mem + offs, buf, len)) {
+ if (!xc->curtime) {
+ int i;
+ for (i = 0; i < len; i++) {
+ if (buf[i] != 'x')
+ break;
+ }
+
+ if (i < len)
+ return;
+ } else {
+ return;
+ }
+ }
+ }
+
+ memcpy(xc->curval_mem + offs, buf, len);
+ } else {
+ if ((vm4ip[3] == xc->tchn_idx) && (vm4ip[2])) {
+ unsigned char *old_value = xc->vchg_mem + vm4ip[2] + 4; /* the +4 skips old vm4ip[2] value */
+ while (*(old_value++) & 0x80) { /* skips over varint encoded "xc->tchn_idx - vm4ip[3]" */
+ }
+ *old_value = *buf; /* overlay new value */
+
+ *(xc->curval_mem + offs) = *buf;
+ return;
+ } else {
+ if ((*(xc->curval_mem + offs)) == (*buf)) {
+ if (!xc->curtime) {
+ if (*buf != 'x')
+ return;
+ } else {
+ return;
+ }
+ }
+ }
+
+ *(xc->curval_mem + offs) = *buf;
+ }
+#endif
+ xc->vchg_siz += fstWriterUint32WithVarint32(xc, &vm4ip[2], xc->tchn_idx - vm4ip[3], buf,
+ len); /* do one fwrite op only */
+ vm4ip[3] = xc->tchn_idx;
+ vm4ip[2] = fpos;
+ } else {
+ offs = vm4ip[0];
+ memcpy(xc->curval_mem + offs, buf, len);
+ }
+ }
+ }
+}
+
+void fstWriterEmitValueChange32(void *ctx, fstHandle handle, uint32_t bits, uint32_t val)
+{
+ char buf[32];
+ char *s = buf;
+ uint32_t i;
+ for (i = 0; i < bits; ++i) {
+ *s++ = '0' + ((val >> (bits - i - 1)) & 1);
+ }
+ fstWriterEmitValueChange(ctx, handle, buf);
+}
+void fstWriterEmitValueChange64(void *ctx, fstHandle handle, uint32_t bits, uint64_t val)
+{
+ char buf[64];
+ char *s = buf;
+ uint32_t i;
+ for (i = 0; i < bits; ++i) {
+ *s++ = '0' + ((val >> (bits - i - 1)) & 1);
+ }
+ fstWriterEmitValueChange(ctx, handle, buf);
+}
+void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle, uint32_t bits, const uint32_t *val)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (FST_UNLIKELY(bits <= 32)) {
+ fstWriterEmitValueChange32(ctx, handle, bits, val[0]);
+ } else if (FST_LIKELY(xc)) {
+ int bq = bits / 32;
+ int br = bits & 31;
+ int i;
+ int w;
+ uint32_t v;
+ unsigned char *s;
+ if (FST_UNLIKELY(bits > xc->outval_alloc_siz)) {
+ xc->outval_alloc_siz = bits * 2 + 1;
+ xc->outval_mem = (unsigned char *)realloc(xc->outval_mem, xc->outval_alloc_siz);
+ if (FST_UNLIKELY(!xc->outval_mem)) {
+ fprintf(stderr, FST_APIMESS "Could not realloc() in fstWriterEmitValueChangeVec32, exiting.\n");
+ exit(255);
+ }
+ }
+ s = xc->outval_mem;
+ {
+ w = bq;
+ v = val[w];
+ for (i = 0; i < br; ++i) {
+ *s++ = '0' + ((v >> (br - i - 1)) & 1);
+ }
+ }
+ for (w = bq - 1; w >= 0; --w) {
+ v = val[w];
+ for (i = (32 - 4); i >= 0; i -= 4) {
+ s[0] = '0' + ((v >> (i + 3)) & 1);
+ s[1] = '0' + ((v >> (i + 2)) & 1);
+ s[2] = '0' + ((v >> (i + 1)) & 1);
+ s[3] = '0' + ((v >> (i + 0)) & 1);
+ s += 4;
+ }
+ }
+ fstWriterEmitValueChange(ctx, handle, xc->outval_mem);
+ }
+}
+void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle, uint32_t bits, const uint64_t *val)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ if (FST_UNLIKELY(bits <= 64)) {
+ fstWriterEmitValueChange64(ctx, handle, bits, val[0]);
+ } else if (FST_LIKELY(xc)) {
+ int bq = bits / 64;
+ int br = bits & 63;
+ int i;
+ int w;
+ uint32_t v;
+ unsigned char *s;
+ if (FST_UNLIKELY(bits > xc->outval_alloc_siz)) {
+ xc->outval_alloc_siz = bits * 2 + 1;
+ xc->outval_mem = (unsigned char *)realloc(xc->outval_mem, xc->outval_alloc_siz);
+ if (FST_UNLIKELY(!xc->outval_mem)) {
+ fprintf(stderr, FST_APIMESS "Could not realloc() in fstWriterEmitValueChangeVec64, exiting.\n");
+ exit(255);
+ }
+ }
+ s = xc->outval_mem;
+ {
+ w = bq;
+ v = val[w];
+ for (i = 0; i < br; ++i) {
+ *s++ = '0' + ((v >> (br - i - 1)) & 1);
+ }
+ }
+ for (w = bq - 1; w >= 0; --w) {
+ v = val[w];
+ for (i = (64 - 4); i >= 0; i -= 4) {
+ s[0] = '0' + ((v >> (i + 3)) & 1);
+ s[1] = '0' + ((v >> (i + 2)) & 1);
+ s[2] = '0' + ((v >> (i + 1)) & 1);
+ s[3] = '0' + ((v >> (i + 0)) & 1);
+ s += 4;
+ }
+ }
+ fstWriterEmitValueChange(ctx, handle, xc->outval_mem);
+ }
+}
+
+void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const void *val, uint32_t len)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ const unsigned char *buf = (const unsigned char *)val;
+
+ if (FST_LIKELY((xc) && (handle <= xc->maxhandle))) {
+ uint32_t fpos;
+ uint32_t *vm4ip;
+
+ if (FST_UNLIKELY(!xc->valpos_mem)) {
+ xc->vc_emitted = 1;
+ fstWriterCreateMmaps(xc);
+ }
+
+ handle--; /* move starting at 1 index to starting at 0 */
+ vm4ip = &(xc->valpos_mem[4 * handle]);
+
+ /* there is no initial time dump for variable length value changes */
+ if (FST_LIKELY(!vm4ip[1])) /* len of zero = variable length */
+ {
+ fpos = xc->vchg_siz;
+
+ if (FST_UNLIKELY((fpos + len + 10 + 5) > xc->vchg_alloc_siz)) {
+ xc->vchg_alloc_siz +=
+ (xc->fst_break_add_size + len +
+ 5); /* +len added in the case of extremely long vectors and small break add sizes */
+ xc->vchg_mem = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz);
+ if (FST_UNLIKELY(!xc->vchg_mem)) {
+ fprintf(stderr,
+ FST_APIMESS "Could not realloc() in fstWriterEmitVariableLengthValueChange, exiting.\n");
+ exit(255);
+ }
+ }
+
+ xc->vchg_siz += fstWriterUint32WithVarint32AndLength(xc, &vm4ip[2], xc->tchn_idx - vm4ip[3], buf,
+ len); /* do one fwrite op only */
+ vm4ip[3] = xc->tchn_idx;
+ vm4ip[2] = fpos;
+ }
+ }
+}
+
+void fstWriterEmitTimeChange(void *ctx, uint64_t tim)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+ unsigned int i;
+ int skip = 0;
+ if (xc) {
+ if (FST_UNLIKELY(xc->is_initial_time)) {
+ if (xc->size_limit_locked) /* this resets xc->is_initial_time to one */
+ {
+ return;
+ }
+
+ if (!xc->valpos_mem) {
+ fstWriterCreateMmaps(xc);
+ }
+
+ skip = 1;
+
+ xc->firsttime = (xc->vc_emitted) ? 0 : tim;
+ xc->curtime = 0;
+ xc->vchg_mem[0] = '!';
+ xc->vchg_siz = 1;
+ fstWriterEmitSectionHeader(xc);
+ for (i = 0; i < xc->maxhandle; i++) {
+ xc->valpos_mem[4 * i + 2] = 0; /* zero out offset val */
+ xc->valpos_mem[4 * i + 3] = 0; /* zero out last time change val */
+ }
+ xc->is_initial_time = 0;
+ } else {
+ if ((xc->vchg_siz >= xc->fst_break_size) || (xc->flush_context_pending)) {
+ xc->flush_context_pending = 0;
+ fstWriterFlushContextPrivate(xc);
+ xc->tchn_cnt++;
+ fstWriterVarint(xc->tchn_handle, xc->curtime);
+ }
+ }
+
+ if (!skip) {
+ xc->tchn_idx++;
+ }
+ fstWriterVarint(xc->tchn_handle, tim - xc->curtime);
+ xc->tchn_cnt++;
+ xc->curtime = tim;
+ }
+}
+
+void fstWriterEmitDumpActive(void *ctx, int enable)
+{
+ struct fstWriterContext *xc = (struct fstWriterContext *)ctx;
+
+ if (xc) {
+ struct fstBlackoutChain *b = (struct fstBlackoutChain *)calloc(1, sizeof(struct fstBlackoutChain));
+
+ b->tim = xc->curtime;
+ b->active = (enable != 0);
+
+ xc->num_blackouts++;
+ if (xc->blackout_curr) {
+ xc->blackout_curr->next = b;
+ xc->blackout_curr = b;
+ } else {
+ xc->blackout_head = b;
+ xc->blackout_curr = b;
+ }
+ }
+}
+
+/***********************/
+/*** ***/
+/*** reader function ***/
+/*** ***/
+/***********************/
+
+/*
+ * private structs
+ */
+static const char *vartypes[] = {"event", "integer", "parameter", "real", "real_parameter", "reg", "supply0",
+ "supply1", "time", "tri", "triand", "trior", "trireg", "tri0",
+ "tri1", "wand", "wire", "wor", "port", "sparray", "realtime",
+ "string", "bit", "logic", "int", "shortint", "longint", "byte",
+ "enum", "shortreal"};
+
+static const char *modtypes[] = {"module",
+ "task",
+ "function",
+ "begin",
+ "fork",
+ "generate",
+ "struct",
+ "union",
+ "class",
+ "interface",
+ "package",
+ "program",
+ "vhdl_architecture",
+ "vhdl_procedure",
+ "vhdl_function",
+ "vhdl_record",
+ "vhdl_process",
+ "vhdl_block",
+ "vhdl_for_generate",
+ "vhdl_if_generate",
+ "vhdl_generate",
+ "vhdl_package"};
+
+static const char *attrtypes[] = {"misc", "array", "enum", "class"};
+
+static const char *arraytypes[] = {"none", "unpacked", "packed", "sparse"};
+
+static const char *enumvaluetypes[] = {"integer",
+ "bit",
+ "logic",
+ "int",
+ "shortint",
+ "longint",
+ "byte",
+ "unsigned_integer",
+ "unsigned_bit",
+ "unsigned_logic",
+ "unsigned_int",
+ "unsigned_shortint",
+ "unsigned_longint",
+ "unsigned_byte"};
+
+static const char *packtypes[] = {"none", "unpacked", "packed", "tagged_packed"};
+
+struct fstCurrHier
+{
+ struct fstCurrHier *prev;
+ void *user_info;
+ int len;
+};
+
+struct fstReaderContext
+{
+ /* common entries */
+
+ FILE *f, *fh;
+
+ uint64_t start_time, end_time;
+ uint64_t mem_used_by_writer;
+ uint64_t scope_count;
+ uint64_t var_count;
+ fstHandle maxhandle;
+ uint64_t num_alias;
+ uint64_t vc_section_count;
+
+ uint32_t *signal_lens; /* maxhandle sized */
+ unsigned char *signal_typs; /* maxhandle sized */
+ unsigned char *process_mask; /* maxhandle-based, bitwise sized */
+ uint32_t longest_signal_value_len; /* longest len value encountered */
+ unsigned char *temp_signal_value_buf; /* malloced for len in longest_signal_value_len */
+
+ signed char timescale;
+ unsigned char filetype;
+
+ unsigned use_vcd_extensions : 1;
+ unsigned double_endian_match : 1;
+ unsigned native_doubles_for_cb : 1;
+ unsigned contains_geom_section : 1;
+ unsigned contains_hier_section : 1; /* valid for hier_pos */
+ unsigned contains_hier_section_lz4duo : 1; /* valid for hier_pos (contains_hier_section_lz4 always also set) */
+ unsigned contains_hier_section_lz4 : 1; /* valid for hier_pos */
+ unsigned limit_range_valid : 1; /* valid for limit_range_start, limit_range_end */
+
+ char version[FST_HDR_SIM_VERSION_SIZE + 1];
+ char date[FST_HDR_DATE_SIZE + 1];
+ int64_t timezero;
+
+ char *filename, *filename_unpacked;
+ fst_off_t hier_pos;
+
+ uint32_t num_blackouts;
+ uint64_t *blackout_times;
+ unsigned char *blackout_activity;
+
+ uint64_t limit_range_start, limit_range_end;
+
+ /* entries specific to read value at time functions */
+
+ unsigned rvat_data_valid : 1;
+ uint64_t *rvat_time_table;
+ uint64_t rvat_beg_tim, rvat_end_tim;
+ unsigned char *rvat_frame_data;
+ uint64_t rvat_frame_maxhandle;
+ fst_off_t *rvat_chain_table;
+ uint32_t *rvat_chain_table_lengths;
+ uint64_t rvat_vc_maxhandle;
+ fst_off_t rvat_vc_start;
+ uint32_t *rvat_sig_offs;
+ int rvat_packtype;
+
+ uint32_t rvat_chain_len;
+ unsigned char *rvat_chain_mem;
+ fstHandle rvat_chain_facidx;
+
+ uint32_t rvat_chain_pos_tidx;
+ uint32_t rvat_chain_pos_idx;
+ uint64_t rvat_chain_pos_time;
+ unsigned rvat_chain_pos_valid : 1;
+
+ /* entries specific to hierarchy traversal */
+
+ struct fstHier hier;
+ struct fstCurrHier *curr_hier;
+ fstHandle current_handle;
+ char *curr_flat_hier_nam;
+ int flat_hier_alloc_len;
+ unsigned do_rewind : 1;
+ char str_scope_nam[FST_ID_NAM_SIZ + 1];
+ char str_scope_comp[FST_ID_NAM_SIZ + 1];
+
+ unsigned fseek_failed : 1;
+
+ /* self-buffered I/O for writes */
+
+#ifndef FST_WRITEX_DISABLE
+ int writex_pos;
+ int writex_fd;
+ unsigned char writex_buf[FST_WRITEX_MAX];
+#endif
+
+ char *f_nam;
+ char *fh_nam;
+};
+
+int fstReaderFseeko(struct fstReaderContext *xc, FILE *stream, fst_off_t offset, int whence)
+{
+ int rc = fseeko(stream, offset, whence);
+
+ if (rc < 0) {
+ xc->fseek_failed = 1;
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "Seek to #%" PRId64 " (whence = %d) failed!\n", offset, whence);
+ perror("Why");
+#endif
+ }
+
+ return (rc);
+}
+
+#ifndef FST_WRITEX_DISABLE
+static void fstWritex(struct fstReaderContext *xc, void *v, int len)
+{
+ unsigned char *s = (unsigned char *)v;
+
+ if (len) {
+ if (len < FST_WRITEX_MAX) {
+ if (xc->writex_pos + len >= FST_WRITEX_MAX) {
+ fstWritex(xc, NULL, 0);
+ }
+
+ memcpy(xc->writex_buf + xc->writex_pos, s, len);
+ xc->writex_pos += len;
+ } else {
+ fstWritex(xc, NULL, 0);
+ if (write(xc->writex_fd, s, len)) {
+ };
+ }
+ } else {
+ if (xc->writex_pos) {
+ if (write(xc->writex_fd, xc->writex_buf, xc->writex_pos)) {
+ };
+ xc->writex_pos = 0;
+ }
+ }
+}
+#endif
+
+/*
+ * scope -> flat name handling
+ */
+static void fstReaderDeallocateScopeData(struct fstReaderContext *xc)
+{
+ struct fstCurrHier *chp;
+
+ free(xc->curr_flat_hier_nam);
+ xc->curr_flat_hier_nam = NULL;
+ while (xc->curr_hier) {
+ chp = xc->curr_hier->prev;
+ free(xc->curr_hier);
+ xc->curr_hier = chp;
+ }
+}
+
+const char *fstReaderGetCurrentFlatScope(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ if (xc) {
+ return (xc->curr_flat_hier_nam ? xc->curr_flat_hier_nam : "");
+ } else {
+ return (NULL);
+ }
+}
+
+void *fstReaderGetCurrentScopeUserInfo(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ if (xc) {
+ return (xc->curr_hier ? xc->curr_hier->user_info : NULL);
+ } else {
+ return (NULL);
+ }
+}
+
+const char *fstReaderPopScope(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ if (xc && xc->curr_hier) {
+ struct fstCurrHier *ch = xc->curr_hier;
+ if (xc->curr_hier->prev) {
+ xc->curr_flat_hier_nam[xc->curr_hier->prev->len] = 0;
+ } else {
+ *xc->curr_flat_hier_nam = 0;
+ }
+ xc->curr_hier = xc->curr_hier->prev;
+ free(ch);
+ return (xc->curr_flat_hier_nam ? xc->curr_flat_hier_nam : "");
+ }
+
+ return (NULL);
+}
+
+void fstReaderResetScope(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ while (fstReaderPopScope(xc))
+ ; /* remove any already-built scoping info */
+ }
+}
+
+const char *fstReaderPushScope(void *ctx, const char *nam, void *user_info)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ if (xc) {
+ struct fstCurrHier *ch = (struct fstCurrHier *)malloc(sizeof(struct fstCurrHier));
+ int chl = xc->curr_hier ? xc->curr_hier->len : 0;
+ int len = chl + 1 + strlen(nam);
+ if (len >= xc->flat_hier_alloc_len) {
+ xc->curr_flat_hier_nam =
+ xc->curr_flat_hier_nam ? (char *)realloc(xc->curr_flat_hier_nam, len + 1) : (char *)malloc(len + 1);
+ }
+
+ if (chl) {
+ xc->curr_flat_hier_nam[chl] = '.';
+ strcpy(xc->curr_flat_hier_nam + chl + 1, nam);
+ } else {
+ strcpy(xc->curr_flat_hier_nam, nam);
+ len--;
+ }
+
+ ch->len = len;
+ ch->prev = xc->curr_hier;
+ ch->user_info = user_info;
+ xc->curr_hier = ch;
+ return (xc->curr_flat_hier_nam);
+ }
+
+ return (NULL);
+}
+
+int fstReaderGetCurrentScopeLen(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc && xc->curr_hier) {
+ return (xc->curr_hier->len);
+ }
+
+ return (0);
+}
+
+int fstReaderGetFseekFailed(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ if (xc) {
+ return (xc->fseek_failed != 0);
+ }
+
+ return (0);
+}
+
+/*
+ * iter mask manipulation util functions
+ */
+int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ facidx--;
+ if (facidx < xc->maxhandle) {
+ int process_idx = facidx / 8;
+ int process_bit = facidx & 7;
+
+ return ((xc->process_mask[process_idx] & (1 << process_bit)) != 0);
+ }
+ }
+ return (0);
+}
+
+void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ facidx--;
+ if (facidx < xc->maxhandle) {
+ int idx = facidx / 8;
+ int bitpos = facidx & 7;
+
+ xc->process_mask[idx] |= (1 << bitpos);
+ }
+ }
+}
+
+void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ facidx--;
+ if (facidx < xc->maxhandle) {
+ int idx = facidx / 8;
+ int bitpos = facidx & 7;
+
+ xc->process_mask[idx] &= (~(1 << bitpos));
+ }
+ }
+}
+
+void fstReaderSetFacProcessMaskAll(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ memset(xc->process_mask, 0xff, (xc->maxhandle + 7) / 8);
+ }
+}
+
+void fstReaderClrFacProcessMaskAll(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ memset(xc->process_mask, 0x00, (xc->maxhandle + 7) / 8);
+ }
+}
+
+/*
+ * various utility read/write functions
+ */
+signed char fstReaderGetTimescale(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->timescale : 0);
+}
+
+uint64_t fstReaderGetStartTime(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->start_time : 0);
+}
+
+uint64_t fstReaderGetEndTime(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->end_time : 0);
+}
+
+uint64_t fstReaderGetMemoryUsedByWriter(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->mem_used_by_writer : 0);
+}
+
+uint64_t fstReaderGetScopeCount(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->scope_count : 0);
+}
+
+uint64_t fstReaderGetVarCount(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->var_count : 0);
+}
+
+fstHandle fstReaderGetMaxHandle(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->maxhandle : 0);
+}
+
+uint64_t fstReaderGetAliasCount(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->num_alias : 0);
+}
+
+uint64_t fstReaderGetValueChangeSectionCount(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->vc_section_count : 0);
+}
+
+int fstReaderGetDoubleEndianMatchState(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->double_endian_match : 0);
+}
+
+const char *fstReaderGetVersionString(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->version : NULL);
+}
+
+const char *fstReaderGetDateString(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->date : NULL);
+}
+
+int fstReaderGetFileType(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? (int)xc->filetype : (int)FST_FT_VERILOG);
+}
+
+int64_t fstReaderGetTimezero(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->timezero : 0);
+}
+
+uint32_t fstReaderGetNumberDumpActivityChanges(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ return (xc ? xc->num_blackouts : 0);
+}
+
+uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc && (idx < xc->num_blackouts) && (xc->blackout_times)) {
+ return (xc->blackout_times[idx]);
+ } else {
+ return (0);
+ }
+}
+
+unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc && (idx < xc->num_blackouts) && (xc->blackout_activity)) {
+ return (xc->blackout_activity[idx]);
+ } else {
+ return (0);
+ }
+}
+
+void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ xc->limit_range_valid = 1;
+ xc->limit_range_start = start_time;
+ xc->limit_range_end = end_time;
+ }
+}
+
+void fstReaderSetUnlimitedTimeRange(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ xc->limit_range_valid = 0;
+ }
+}
+
+void fstReaderSetVcdExtensions(void *ctx, int enable)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ xc->use_vcd_extensions = (enable != 0);
+ }
+}
+
+void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ if (xc) {
+ xc->native_doubles_for_cb = (enable != 0);
+ }
+}
+
+/*
+ * hierarchy processing
+ */
+static void fstVcdID(char *buf, unsigned int value)
+{
+ char *pnt = buf;
+
+ /* zero is illegal for a value...it is assumed they start at one */
+ while (value) {
+ value--;
+ *(pnt++) = (char)('!' + value % 94);
+ value = value / 94;
+ }
+
+ *pnt = 0;
+}
+
+static int fstVcdIDForFwrite(char *buf, unsigned int value)
+{
+ char *pnt = buf;
+
+ /* zero is illegal for a value...it is assumed they start at one */
+ while (value) {
+ value--;
+ *(pnt++) = (char)('!' + value % 94);
+ value = value / 94;
+ }
+
+ return (pnt - buf);
+}
+
+static int fstReaderRecreateHierFile(struct fstReaderContext *xc)
+{
+ int pass_status = 1;
+
+ if (!xc->fh) {
+ fst_off_t offs_cache = ftello(xc->f);
+ char *fnam = (char *)malloc(strlen(xc->filename) + 6 + 16 + 32 + 1);
+ unsigned char *mem = (unsigned char *)malloc(FST_GZIO_LEN);
+ fst_off_t hl, uclen;
+ fst_off_t clen = 0;
+ gzFile zhandle = NULL;
+ int zfd;
+ int htyp = FST_BL_SKIP;
+
+ /* can't handle both set at once should never happen in a real file */
+ if (!xc->contains_hier_section_lz4 && xc->contains_hier_section) {
+ htyp = FST_BL_HIER;
+ } else if (xc->contains_hier_section_lz4 && !xc->contains_hier_section) {
+ htyp = xc->contains_hier_section_lz4duo ? FST_BL_HIER_LZ4DUO : FST_BL_HIER_LZ4;
+ }
+
+ sprintf(fnam, "%s.hier_%d_%p", xc->filename, getpid(), (void *)xc);
+ fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET);
+ uclen = fstReaderUint64(xc->f);
+#ifndef __MINGW32__
+ fflush(xc->f);
+#endif
+ if (htyp == FST_BL_HIER) {
+ fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET);
+ uclen = fstReaderUint64(xc->f);
+#ifndef __MINGW32__
+ fflush(xc->f);
+#endif
+ zfd = dup(fileno(xc->f));
+ zhandle = gzdopen(zfd, "rb");
+ if (!zhandle) {
+ close(zfd);
+ free(mem);
+ free(fnam);
+ return (0);
+ }
+ } else if ((htyp == FST_BL_HIER_LZ4) || (htyp == FST_BL_HIER_LZ4DUO)) {
+ fstReaderFseeko(xc, xc->f, xc->hier_pos - 8, SEEK_SET); /* get section len */
+ clen = fstReaderUint64(xc->f) - 16;
+ uclen = fstReaderUint64(xc->f);
+#ifndef __MINGW32__
+ fflush(xc->f);
+#endif
+ }
+
+#ifndef __MINGW32__
+ xc->fh = fopen(fnam, "w+b");
+ if (!xc->fh)
+#endif
+ {
+ xc->fh = tmpfile_open(&xc->fh_nam);
+ free(fnam);
+ fnam = NULL;
+ if (!xc->fh) {
+ tmpfile_close(&xc->fh, &xc->fh_nam);
+ free(mem);
+ return (0);
+ }
+ }
+
+#ifndef __MINGW32__
+ if (fnam)
+ unlink(fnam);
+#endif
+
+ if (htyp == FST_BL_HIER) {
+ for (hl = 0; hl < uclen; hl += FST_GZIO_LEN) {
+ size_t len = ((uclen - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - hl);
+ size_t gzreadlen = gzread(zhandle, mem, len); /* rc should equal len... */
+ size_t fwlen;
+
+ if (gzreadlen != len) {
+ pass_status = 0;
+ break;
+ }
+
+ fwlen = fstFwrite(mem, len, 1, xc->fh);
+ if (fwlen != 1) {
+ pass_status = 0;
+ break;
+ }
+ }
+ gzclose(zhandle);
+ } else if (htyp == FST_BL_HIER_LZ4DUO) {
+ unsigned char *lz4_cmem = (unsigned char *)malloc(clen);
+ unsigned char *lz4_ucmem = (unsigned char *)malloc(uclen);
+ unsigned char *lz4_ucmem2;
+ uint64_t uclen2;
+ int skiplen2 = 0;
+
+ fstFread(lz4_cmem, clen, 1, xc->f);
+
+ uclen2 = fstGetVarint64(lz4_cmem, &skiplen2);
+ lz4_ucmem2 = (unsigned char *)malloc(uclen2);
+ pass_status =
+ (uclen2 == (uint64_t)LZ4_decompress_safe_partial((char *)lz4_cmem + skiplen2, (char *)lz4_ucmem2,
+ clen - skiplen2, uclen2, uclen2));
+ if (pass_status) {
+ pass_status = (uclen == LZ4_decompress_safe_partial((char *)lz4_ucmem2, (char *)lz4_ucmem, uclen2,
+ uclen, uclen));
+
+ if (fstFwrite(lz4_ucmem, uclen, 1, xc->fh) != 1) {
+ pass_status = 0;
+ }
+ }
+
+ free(lz4_ucmem2);
+ free(lz4_ucmem);
+ free(lz4_cmem);
+ } else if (htyp == FST_BL_HIER_LZ4) {
+ unsigned char *lz4_cmem = (unsigned char *)malloc(clen);
+ unsigned char *lz4_ucmem = (unsigned char *)malloc(uclen);
+
+ fstFread(lz4_cmem, clen, 1, xc->f);
+ pass_status =
+ (uclen == LZ4_decompress_safe_partial((char *)lz4_cmem, (char *)lz4_ucmem, clen, uclen, uclen));
+
+ if (fstFwrite(lz4_ucmem, uclen, 1, xc->fh) != 1) {
+ pass_status = 0;
+ }
+
+ free(lz4_ucmem);
+ free(lz4_cmem);
+ } else /* FST_BL_SKIP */
+ {
+ pass_status = 0;
+ if (xc->fh) {
+ fclose(xc->fh);
+ xc->fh = NULL; /* needed in case .hier file is missing and there are no hier sections */
+ }
+ }
+
+ free(mem);
+ free(fnam);
+
+ fstReaderFseeko(xc, xc->f, offs_cache, SEEK_SET);
+ }
+
+ return (pass_status);
+}
+
+int fstReaderIterateHierRewind(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ int pass_status = 0;
+
+ if (xc) {
+ pass_status = 1;
+ if (!xc->fh) {
+ pass_status = fstReaderRecreateHierFile(xc);
+ }
+
+ xc->do_rewind = 1;
+ }
+
+ return (pass_status);
+}
+
+struct fstHier *fstReaderIterateHier(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ int isfeof;
+ fstHandle alias;
+ char *pnt;
+ int ch;
+
+ if (!xc)
+ return (NULL);
+
+ if (!xc->fh) {
+ if (!fstReaderRecreateHierFile(xc)) {
+ return (NULL);
+ }
+ }
+
+ if (xc->do_rewind) {
+ xc->do_rewind = 0;
+ xc->current_handle = 0;
+ fstReaderFseeko(xc, xc->fh, 0, SEEK_SET);
+ clearerr(xc->fh);
+ }
+
+ if (!(isfeof = feof(xc->fh))) {
+ int tag = fgetc(xc->fh);
+ switch (tag) {
+ case FST_ST_VCD_SCOPE:
+ xc->hier.htyp = FST_HT_SCOPE;
+ xc->hier.u.scope.typ = fgetc(xc->fh);
+ xc->hier.u.scope.name = pnt = xc->str_scope_nam;
+ while ((ch = fgetc(xc->fh))) {
+ *(pnt++) = ch;
+ }; /* scopename */
+ *pnt = 0;
+ xc->hier.u.scope.name_length = pnt - xc->hier.u.scope.name;
+
+ xc->hier.u.scope.component = pnt = xc->str_scope_comp;
+ while ((ch = fgetc(xc->fh))) {
+ *(pnt++) = ch;
+ }; /* scopecomp */
+ *pnt = 0;
+ xc->hier.u.scope.component_length = pnt - xc->hier.u.scope.component;
+ break;
+
+ case FST_ST_VCD_UPSCOPE:
+ xc->hier.htyp = FST_HT_UPSCOPE;
+ break;
+
+ case FST_ST_GEN_ATTRBEGIN:
+ xc->hier.htyp = FST_HT_ATTRBEGIN;
+ xc->hier.u.attr.typ = fgetc(xc->fh);
+ xc->hier.u.attr.subtype = fgetc(xc->fh);
+ xc->hier.u.attr.name = pnt = xc->str_scope_nam;
+ while ((ch = fgetc(xc->fh))) {
+ *(pnt++) = ch;
+ }; /* scopename */
+ *pnt = 0;
+ xc->hier.u.attr.name_length = pnt - xc->hier.u.scope.name;
+
+ xc->hier.u.attr.arg = fstReaderVarint64(xc->fh);
+
+ if (xc->hier.u.attr.typ == FST_AT_MISC) {
+ if ((xc->hier.u.attr.subtype == FST_MT_SOURCESTEM) || (xc->hier.u.attr.subtype == FST_MT_SOURCEISTEM)) {
+ int sidx_skiplen_dummy = 0;
+ xc->hier.u.attr.arg_from_name =
+ fstGetVarint64((unsigned char *)xc->str_scope_nam, &sidx_skiplen_dummy);
+ }
+ }
+ break;
+
+ case FST_ST_GEN_ATTREND:
+ xc->hier.htyp = FST_HT_ATTREND;
+ break;
+
+ case FST_VT_VCD_EVENT:
+ case FST_VT_VCD_INTEGER:
+ case FST_VT_VCD_PARAMETER:
+ case FST_VT_VCD_REAL:
+ case FST_VT_VCD_REAL_PARAMETER:
+ case FST_VT_VCD_REG:
+ case FST_VT_VCD_SUPPLY0:
+ case FST_VT_VCD_SUPPLY1:
+ case FST_VT_VCD_TIME:
+ case FST_VT_VCD_TRI:
+ case FST_VT_VCD_TRIAND:
+ case FST_VT_VCD_TRIOR:
+ case FST_VT_VCD_TRIREG:
+ case FST_VT_VCD_TRI0:
+ case FST_VT_VCD_TRI1:
+ case FST_VT_VCD_WAND:
+ case FST_VT_VCD_WIRE:
+ case FST_VT_VCD_WOR:
+ case FST_VT_VCD_PORT:
+ case FST_VT_VCD_SPARRAY:
+ case FST_VT_VCD_REALTIME:
+ case FST_VT_GEN_STRING:
+ case FST_VT_SV_BIT:
+ case FST_VT_SV_LOGIC:
+ case FST_VT_SV_INT:
+ case FST_VT_SV_SHORTINT:
+ case FST_VT_SV_LONGINT:
+ case FST_VT_SV_BYTE:
+ case FST_VT_SV_ENUM:
+ case FST_VT_SV_SHORTREAL:
+ xc->hier.htyp = FST_HT_VAR;
+ xc->hier.u.var.svt_workspace = FST_SVT_NONE;
+ xc->hier.u.var.sdt_workspace = FST_SDT_NONE;
+ xc->hier.u.var.sxt_workspace = 0;
+ xc->hier.u.var.typ = tag;
+ xc->hier.u.var.direction = fgetc(xc->fh);
+ xc->hier.u.var.name = pnt = xc->str_scope_nam;
+ while ((ch = fgetc(xc->fh))) {
+ *(pnt++) = ch;
+ }; /* varname */
+ *pnt = 0;
+ xc->hier.u.var.name_length = pnt - xc->hier.u.var.name;
+ xc->hier.u.var.length = fstReaderVarint32(xc->fh);
+ if (tag == FST_VT_VCD_PORT) {
+ xc->hier.u.var.length -= 2; /* removal of delimiting spaces */
+ xc->hier.u.var.length /= 3; /* port -> signal size adjust */
+ }
+
+ alias = fstReaderVarint32(xc->fh);
+
+ if (!alias) {
+ xc->current_handle++;
+ xc->hier.u.var.handle = xc->current_handle;
+ xc->hier.u.var.is_alias = 0;
+ } else {
+ xc->hier.u.var.handle = alias;
+ xc->hier.u.var.is_alias = 1;
+ }
+
+ break;
+
+ default:
+ isfeof = 1;
+ break;
+ }
+ }
+
+ return (!isfeof ? &xc->hier : NULL);
+}
+
+int fstReaderProcessHier(void *ctx, FILE *fv)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ char *str;
+ char *pnt;
+ int ch, scopetype;
+ int vartype;
+ uint32_t len, alias;
+ /* uint32_t maxvalpos=0; */
+ unsigned int num_signal_dyn = 65536;
+ int attrtype, subtype;
+ uint64_t attrarg;
+ fstHandle maxhandle_scanbuild;
+
+ if (!xc)
+ return (0);
+
+ xc->longest_signal_value_len = 32; /* arbitrarily set at 32...this is much longer than an expanded double */
+
+ if (!xc->fh) {
+ if (!fstReaderRecreateHierFile(xc)) {
+ return (0);
+ }
+ }
+
+ str = (char *)malloc(FST_ID_NAM_ATTR_SIZ + 1);
+
+ if (fv) {
+ char time_dimension[2] = {0, 0};
+ int time_scale = 1;
+
+ fprintf(fv, "$date\n\t%s\n$end\n", xc->date);
+ fprintf(fv, "$version\n\t%s\n$end\n", xc->version);
+ if (xc->timezero)
+ fprintf(fv, "$timezero\n\t%" PRId64 "\n$end\n", xc->timezero);
+
+ switch (xc->timescale) {
+ case 2:
+ time_scale = 100;
+ time_dimension[0] = 0;
+ break;
+ case 1:
+ time_scale = 10; /* fallthrough */
+ case 0:
+ time_dimension[0] = 0;
+ break;
+
+ case -1:
+ time_scale = 100;
+ time_dimension[0] = 'm';
+ break;
+ case -2:
+ time_scale = 10; /* fallthrough */
+ case -3:
+ time_dimension[0] = 'm';
+ break;
+
+ case -4:
+ time_scale = 100;
+ time_dimension[0] = 'u';
+ break;
+ case -5:
+ time_scale = 10; /* fallthrough */
+ case -6:
+ time_dimension[0] = 'u';
+ break;
+
+ case -10:
+ time_scale = 100;
+ time_dimension[0] = 'p';
+ break;
+ case -11:
+ time_scale = 10; /* fallthrough */
+ case -12:
+ time_dimension[0] = 'p';
+ break;
+
+ case -13:
+ time_scale = 100;
+ time_dimension[0] = 'f';
+ break;
+ case -14:
+ time_scale = 10; /* fallthrough */
+ case -15:
+ time_dimension[0] = 'f';
+ break;
+
+ case -16:
+ time_scale = 100;
+ time_dimension[0] = 'a';
+ break;
+ case -17:
+ time_scale = 10; /* fallthrough */
+ case -18:
+ time_dimension[0] = 'a';
+ break;
+
+ case -19:
+ time_scale = 100;
+ time_dimension[0] = 'z';
+ break;
+ case -20:
+ time_scale = 10; /* fallthrough */
+ case -21:
+ time_dimension[0] = 'z';
+ break;
+
+ case -7:
+ time_scale = 100;
+ time_dimension[0] = 'n';
+ break;
+ case -8:
+ time_scale = 10; /* fallthrough */
+ case -9:
+ default:
+ time_dimension[0] = 'n';
+ break;
+ }
+
+ if (fv)
+ fprintf(fv, "$timescale\n\t%d%ss\n$end\n", time_scale, time_dimension);
+ }
+
+ xc->maxhandle = 0;
+ xc->num_alias = 0;
+
+ free(xc->signal_lens);
+ xc->signal_lens = (uint32_t *)malloc(num_signal_dyn * sizeof(uint32_t));
+
+ free(xc->signal_typs);
+ xc->signal_typs = (unsigned char *)malloc(num_signal_dyn * sizeof(unsigned char));
+
+ fstReaderFseeko(xc, xc->fh, 0, SEEK_SET);
+ while (!feof(xc->fh)) {
+ int tag = fgetc(xc->fh);
+ switch (tag) {
+ case FST_ST_VCD_SCOPE:
+ scopetype = fgetc(xc->fh);
+ if ((scopetype < FST_ST_MIN) || (scopetype > FST_ST_MAX))
+ scopetype = FST_ST_VCD_MODULE;
+ pnt = str;
+ while ((ch = fgetc(xc->fh))) {
+ *(pnt++) = ch;
+ }; /* scopename */
+ *pnt = 0;
+ while (fgetc(xc->fh)) {
+ }; /* scopecomp */
+
+ if (fv)
+ fprintf(fv, "$scope %s %s $end\n", modtypes[scopetype], str);
+ break;
+
+ case FST_ST_VCD_UPSCOPE:
+ if (fv)
+ fprintf(fv, "$upscope $end\n");
+ break;
+
+ case FST_ST_GEN_ATTRBEGIN:
+ attrtype = fgetc(xc->fh);
+ subtype = fgetc(xc->fh);
+ pnt = str;
+ while ((ch = fgetc(xc->fh))) {
+ *(pnt++) = ch;
+ }; /* attrname */
+ *pnt = 0;
+
+ if (!str[0]) {
+ strcpy(str, "\"\"");
+ }
+
+ attrarg = fstReaderVarint64(xc->fh);
+
+ if (fv && xc->use_vcd_extensions) {
+ switch (attrtype) {
+ case FST_AT_ARRAY:
+ if ((subtype < FST_AR_NONE) || (subtype > FST_AR_MAX))
+ subtype = FST_AR_NONE;
+ fprintf(fv, "$attrbegin %s %s %s %" PRId64 " $end\n", attrtypes[attrtype], arraytypes[subtype], str,
+ attrarg);
+ break;
+ case FST_AT_ENUM:
+ if ((subtype < FST_EV_SV_INTEGER) || (subtype > FST_EV_MAX))
+ subtype = FST_EV_SV_INTEGER;
+ fprintf(fv, "$attrbegin %s %s %s %" PRId64 " $end\n", attrtypes[attrtype], enumvaluetypes[subtype],
+ str, attrarg);
+ break;
+ case FST_AT_PACK:
+ if ((subtype < FST_PT_NONE) || (subtype > FST_PT_MAX))
+ subtype = FST_PT_NONE;
+ fprintf(fv, "$attrbegin %s %s %s %" PRId64 " $end\n", attrtypes[attrtype], packtypes[subtype], str,
+ attrarg);
+ break;
+ case FST_AT_MISC:
+ default:
+ attrtype = FST_AT_MISC;
+ if (subtype == FST_MT_COMMENT) {
+ fprintf(fv, "$comment\n\t%s\n$end\n", str);
+ } else {
+ if ((subtype == FST_MT_SOURCESTEM) || (subtype == FST_MT_SOURCEISTEM)) {
+ int sidx_skiplen_dummy = 0;
+ uint64_t sidx = fstGetVarint64((unsigned char *)str, &sidx_skiplen_dummy);
+
+ fprintf(fv, "$attrbegin %s %02x %" PRId64 " %" PRId64 " $end\n", attrtypes[attrtype],
+ subtype, sidx, attrarg);
+ } else {
+ fprintf(fv, "$attrbegin %s %02x %s %" PRId64 " $end\n", attrtypes[attrtype], subtype, str,
+ attrarg);
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case FST_ST_GEN_ATTREND:
+ if (fv && xc->use_vcd_extensions)
+ fprintf(fv, "$attrend $end\n");
+ break;
+
+ case FST_VT_VCD_EVENT:
+ case FST_VT_VCD_INTEGER:
+ case FST_VT_VCD_PARAMETER:
+ case FST_VT_VCD_REAL:
+ case FST_VT_VCD_REAL_PARAMETER:
+ case FST_VT_VCD_REG:
+ case FST_VT_VCD_SUPPLY0:
+ case FST_VT_VCD_SUPPLY1:
+ case FST_VT_VCD_TIME:
+ case FST_VT_VCD_TRI:
+ case FST_VT_VCD_TRIAND:
+ case FST_VT_VCD_TRIOR:
+ case FST_VT_VCD_TRIREG:
+ case FST_VT_VCD_TRI0:
+ case FST_VT_VCD_TRI1:
+ case FST_VT_VCD_WAND:
+ case FST_VT_VCD_WIRE:
+ case FST_VT_VCD_WOR:
+ case FST_VT_VCD_PORT:
+ case FST_VT_VCD_SPARRAY:
+ case FST_VT_VCD_REALTIME:
+ case FST_VT_GEN_STRING:
+ case FST_VT_SV_BIT:
+ case FST_VT_SV_LOGIC:
+ case FST_VT_SV_INT:
+ case FST_VT_SV_SHORTINT:
+ case FST_VT_SV_LONGINT:
+ case FST_VT_SV_BYTE:
+ case FST_VT_SV_ENUM:
+ case FST_VT_SV_SHORTREAL:
+ vartype = tag;
+ /* vardir = */ fgetc(xc->fh); /* unused in VCD reader, but need to advance read pointer */
+ pnt = str;
+ while ((ch = fgetc(xc->fh))) {
+ *(pnt++) = ch;
+ }; /* varname */
+ *pnt = 0;
+ len = fstReaderVarint32(xc->fh);
+ alias = fstReaderVarint32(xc->fh);
+
+ if (!alias) {
+ if (xc->maxhandle == num_signal_dyn) {
+ num_signal_dyn *= 2;
+ xc->signal_lens = (uint32_t *)realloc(xc->signal_lens, num_signal_dyn * sizeof(uint32_t));
+ xc->signal_typs = (unsigned char *)realloc(xc->signal_typs, num_signal_dyn * sizeof(unsigned char));
+ }
+ xc->signal_lens[xc->maxhandle] = len;
+ xc->signal_typs[xc->maxhandle] = vartype;
+
+ /* maxvalpos+=len; */
+ if (len > xc->longest_signal_value_len) {
+ xc->longest_signal_value_len = len;
+ }
+
+ if ((vartype == FST_VT_VCD_REAL) || (vartype == FST_VT_VCD_REAL_PARAMETER) ||
+ (vartype == FST_VT_VCD_REALTIME) || (vartype == FST_VT_SV_SHORTREAL)) {
+ len = (vartype != FST_VT_SV_SHORTREAL) ? 64 : 32;
+ xc->signal_typs[xc->maxhandle] = FST_VT_VCD_REAL;
+ }
+ if (fv) {
+ char vcdid_buf[16];
+ uint32_t modlen = (vartype != FST_VT_VCD_PORT) ? len : ((len - 2) / 3);
+ fstVcdID(vcdid_buf, xc->maxhandle + 1);
+ fprintf(fv, "$var %s %" PRIu32 " %s %s $end\n", vartypes[vartype], modlen, vcdid_buf, str);
+ }
+ xc->maxhandle++;
+ } else {
+ if ((vartype == FST_VT_VCD_REAL) || (vartype == FST_VT_VCD_REAL_PARAMETER) ||
+ (vartype == FST_VT_VCD_REALTIME) || (vartype == FST_VT_SV_SHORTREAL)) {
+ len = (vartype != FST_VT_SV_SHORTREAL) ? 64 : 32;
+ xc->signal_typs[xc->maxhandle] = FST_VT_VCD_REAL;
+ }
+ if (fv) {
+ char vcdid_buf[16];
+ uint32_t modlen = (vartype != FST_VT_VCD_PORT) ? len : ((len - 2) / 3);
+ fstVcdID(vcdid_buf, alias);
+ fprintf(fv, "$var %s %" PRIu32 " %s %s $end\n", vartypes[vartype], modlen, vcdid_buf, str);
+ }
+ xc->num_alias++;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (fv)
+ fprintf(fv, "$enddefinitions $end\n");
+
+ maxhandle_scanbuild = xc->maxhandle ? xc->maxhandle
+ : 1; /*scan-build warning suppression, in reality we have at least one signal */
+
+ xc->signal_lens = (uint32_t *)realloc(xc->signal_lens, maxhandle_scanbuild * sizeof(uint32_t));
+ xc->signal_typs = (unsigned char *)realloc(xc->signal_typs, maxhandle_scanbuild * sizeof(unsigned char));
+
+ free(xc->process_mask);
+ xc->process_mask = (unsigned char *)calloc(1, (maxhandle_scanbuild + 7) / 8);
+
+ free(xc->temp_signal_value_buf);
+ xc->temp_signal_value_buf = (unsigned char *)malloc(xc->longest_signal_value_len + 1);
+
+ xc->var_count = xc->maxhandle + xc->num_alias;
+
+ free(str);
+ return (1);
+}
+
+/*
+ * reader file open/close functions
+ */
+int fstReaderInit(struct fstReaderContext *xc)
+{
+ fst_off_t blkpos = 0;
+ fst_off_t endfile;
+ uint64_t seclen;
+ int sectype;
+ uint64_t vc_section_count_actual = 0;
+ int hdr_incomplete = 0;
+ int hdr_seen = 0;
+ int gzread_pass_status = 1;
+
+ sectype = fgetc(xc->f);
+ if (sectype == FST_BL_ZWRAPPER) {
+ FILE *fcomp;
+ fst_off_t offpnt, uclen;
+ char gz_membuf[FST_GZIO_LEN];
+ gzFile zhandle;
+ int zfd;
+ int flen = strlen(xc->filename);
+ char *hf;
+
+ seclen = fstReaderUint64(xc->f);
+ uclen = fstReaderUint64(xc->f);
+
+ if (!seclen)
+ return (0); /* not finished compressing, this is a failed read */
+
+ hf = (char *)calloc(1, flen + 16 + 32 + 1);
+
+ sprintf(hf, "%s.upk_%d_%p", xc->filename, getpid(), (void *)xc);
+ fcomp = fopen(hf, "w+b");
+ if (!fcomp) {
+ fcomp = tmpfile_open(&xc->f_nam);
+ free(hf);
+ hf = NULL;
+ if (!fcomp) {
+ tmpfile_close(&fcomp, &xc->f_nam);
+ return (0);
+ }
+ }
+
+#if defined(FST_MACOSX)
+ setvbuf(fcomp, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */
+#endif
+
+#ifdef __MINGW32__
+ setvbuf(fcomp, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */
+ xc->filename_unpacked = hf;
+#else
+ if (hf) {
+ unlink(hf);
+ free(hf);
+ }
+#endif
+
+ fstReaderFseeko(xc, xc->f, 1 + 8 + 8, SEEK_SET);
+#ifndef __MINGW32__
+ fflush(xc->f);
+#endif
+
+ zfd = dup(fileno(xc->f));
+ zhandle = gzdopen(zfd, "rb");
+ if (zhandle) {
+ for (offpnt = 0; offpnt < uclen; offpnt += FST_GZIO_LEN) {
+ size_t this_len = ((uclen - offpnt) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - offpnt);
+ size_t gzreadlen = gzread(zhandle, gz_membuf, this_len);
+ size_t fwlen;
+
+ if (gzreadlen != this_len) {
+ gzread_pass_status = 0;
+ break;
+ }
+ fwlen = fstFwrite(gz_membuf, this_len, 1, fcomp);
+ if (fwlen != 1) {
+ gzread_pass_status = 0;
+ break;
+ }
+ }
+ gzclose(zhandle);
+ } else {
+ close(zfd);
+ }
+ fflush(fcomp);
+ fclose(xc->f);
+ xc->f = fcomp;
+ }
+
+ if (gzread_pass_status) {
+ fstReaderFseeko(xc, xc->f, 0, SEEK_END);
+ endfile = ftello(xc->f);
+
+ while (blkpos < endfile) {
+ fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET);
+
+ sectype = fgetc(xc->f);
+ seclen = fstReaderUint64(xc->f);
+
+ if (sectype == EOF) {
+ break;
+ }
+
+ if ((hdr_incomplete) && (!seclen)) {
+ break;
+ }
+
+ if (!hdr_seen && (sectype != FST_BL_HDR)) {
+ break;
+ }
+
+ blkpos++;
+ if (sectype == FST_BL_HDR) {
+ if (!hdr_seen) {
+ int ch;
+ double dcheck;
+
+ xc->start_time = fstReaderUint64(xc->f);
+ xc->end_time = fstReaderUint64(xc->f);
+
+ hdr_incomplete = (xc->start_time == 0) && (xc->end_time == 0);
+
+ fstFread(&dcheck, 8, 1, xc->f);
+ xc->double_endian_match = (dcheck == FST_DOUBLE_ENDTEST);
+ if (!xc->double_endian_match) {
+ union
+ {
+ unsigned char rvs_buf[8];
+ double d;
+ } vu;
+
+ unsigned char *dcheck_alias = (unsigned char *)&dcheck;
+ int rvs_idx;
+
+ for (rvs_idx = 0; rvs_idx < 8; rvs_idx++) {
+ vu.rvs_buf[rvs_idx] = dcheck_alias[7 - rvs_idx];
+ }
+ if (vu.d != FST_DOUBLE_ENDTEST) {
+ break; /* either corrupt file or wrong architecture (offset +33 also functions as matchword)
+ */
+ }
+ }
+
+ hdr_seen = 1;
+
+ xc->mem_used_by_writer = fstReaderUint64(xc->f);
+ xc->scope_count = fstReaderUint64(xc->f);
+ xc->var_count = fstReaderUint64(xc->f);
+ xc->maxhandle = fstReaderUint64(xc->f);
+ xc->num_alias = xc->var_count - xc->maxhandle;
+ xc->vc_section_count = fstReaderUint64(xc->f);
+ ch = fgetc(xc->f);
+ xc->timescale = (signed char)ch;
+ fstFread(xc->version, FST_HDR_SIM_VERSION_SIZE, 1, xc->f);
+ xc->version[FST_HDR_SIM_VERSION_SIZE] = 0;
+ fstFread(xc->date, FST_HDR_DATE_SIZE, 1, xc->f);
+ xc->date[FST_HDR_DATE_SIZE] = 0;
+ ch = fgetc(xc->f);
+ xc->filetype = (unsigned char)ch;
+ xc->timezero = fstReaderUint64(xc->f);
+ }
+ } else if ((sectype == FST_BL_VCDATA) || (sectype == FST_BL_VCDATA_DYN_ALIAS) ||
+ (sectype == FST_BL_VCDATA_DYN_ALIAS2)) {
+ if (hdr_incomplete) {
+ uint64_t bt = fstReaderUint64(xc->f);
+ xc->end_time = fstReaderUint64(xc->f);
+
+ if (!vc_section_count_actual) {
+ xc->start_time = bt;
+ }
+ }
+
+ vc_section_count_actual++;
+ } else if (sectype == FST_BL_GEOM) {
+ if (!hdr_incomplete) {
+ uint64_t clen = seclen - 24;
+ uint64_t uclen = fstReaderUint64(xc->f);
+ unsigned char *ucdata = (unsigned char *)malloc(uclen);
+ unsigned char *pnt = ucdata;
+ unsigned int i;
+
+ xc->contains_geom_section = 1;
+ xc->maxhandle = fstReaderUint64(xc->f);
+ xc->longest_signal_value_len =
+ 32; /* arbitrarily set at 32...this is much longer than an expanded double */
+
+ free(xc->process_mask);
+ xc->process_mask = (unsigned char *)calloc(1, (xc->maxhandle + 7) / 8);
+
+ if (clen != uclen) {
+ unsigned char *cdata = (unsigned char *)malloc(clen);
+ unsigned long destlen = uclen;
+ unsigned long sourcelen = clen;
+ int rc;
+
+ fstFread(cdata, clen, 1, xc->f);
+ rc = uncompress(ucdata, &destlen, cdata, sourcelen);
+
+ if (rc != Z_OK) {
+ fprintf(stderr, FST_APIMESS "fstReaderInit(), geom uncompress rc = %d, exiting.\n", rc);
+ exit(255);
+ }
+
+ free(cdata);
+ } else {
+ fstFread(ucdata, uclen, 1, xc->f);
+ }
+
+ free(xc->signal_lens);
+ xc->signal_lens = (uint32_t *)malloc(sizeof(uint32_t) * xc->maxhandle);
+ free(xc->signal_typs);
+ xc->signal_typs = (unsigned char *)malloc(sizeof(unsigned char) * xc->maxhandle);
+
+ for (i = 0; i < xc->maxhandle; i++) {
+ int skiplen;
+ uint64_t val = fstGetVarint32(pnt, &skiplen);
+
+ pnt += skiplen;
+
+ if (val) {
+ xc->signal_lens[i] = (val != 0xFFFFFFFF) ? val : 0;
+ xc->signal_typs[i] = FST_VT_VCD_WIRE;
+ if (xc->signal_lens[i] > xc->longest_signal_value_len) {
+ xc->longest_signal_value_len = xc->signal_lens[i];
+ }
+ } else {
+ xc->signal_lens[i] = 8; /* backpatch in real */
+ xc->signal_typs[i] = FST_VT_VCD_REAL;
+ /* xc->longest_signal_value_len handled above by overly large init size */
+ }
+ }
+
+ free(xc->temp_signal_value_buf);
+ xc->temp_signal_value_buf = (unsigned char *)malloc(xc->longest_signal_value_len + 1);
+
+ free(ucdata);
+ }
+ } else if (sectype == FST_BL_HIER) {
+ xc->contains_hier_section = 1;
+ xc->hier_pos = ftello(xc->f);
+ } else if (sectype == FST_BL_HIER_LZ4DUO) {
+ xc->contains_hier_section_lz4 = 1;
+ xc->contains_hier_section_lz4duo = 1;
+ xc->hier_pos = ftello(xc->f);
+ } else if (sectype == FST_BL_HIER_LZ4) {
+ xc->contains_hier_section_lz4 = 1;
+ xc->hier_pos = ftello(xc->f);
+ } else if (sectype == FST_BL_BLACKOUT) {
+ uint32_t i;
+ uint64_t cur_bl = 0;
+ uint64_t delta;
+
+ xc->num_blackouts = fstReaderVarint32(xc->f);
+ free(xc->blackout_times);
+ xc->blackout_times = (uint64_t *)calloc(xc->num_blackouts, sizeof(uint64_t));
+ free(xc->blackout_activity);
+ xc->blackout_activity = (unsigned char *)calloc(xc->num_blackouts, sizeof(unsigned char));
+
+ for (i = 0; i < xc->num_blackouts; i++) {
+ xc->blackout_activity[i] = fgetc(xc->f) != 0;
+ delta = fstReaderVarint64(xc->f);
+ cur_bl += delta;
+ xc->blackout_times[i] = cur_bl;
+ }
+ }
+
+ blkpos += seclen;
+ if (!hdr_seen)
+ break;
+ }
+
+ if (hdr_seen) {
+ if (xc->vc_section_count != vc_section_count_actual) {
+ xc->vc_section_count = vc_section_count_actual;
+ }
+
+ if (!xc->contains_geom_section) {
+ fstReaderProcessHier(xc, NULL); /* recreate signal_lens/signal_typs info */
+ }
+ }
+ }
+
+ return (hdr_seen);
+}
+
+void *fstReaderOpenForUtilitiesOnly(void)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)calloc(1, sizeof(struct fstReaderContext));
+
+ return (xc);
+}
+
+void *fstReaderOpen(const char *nam)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)calloc(1, sizeof(struct fstReaderContext));
+
+ if ((!nam) || (!(xc->f = fopen(nam, "rb")))) {
+ free(xc);
+ xc = NULL;
+ } else {
+ int flen = strlen(nam);
+ char *hf = (char *)calloc(1, flen + 6);
+ int rc;
+
+#if defined(__MINGW32__) || defined(FST_MACOSX)
+ setvbuf(xc->f, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */
+#endif
+
+ memcpy(hf, nam, flen);
+ strcpy(hf + flen, ".hier");
+ xc->fh = fopen(hf, "rb");
+
+ free(hf);
+ xc->filename = strdup(nam);
+ rc = fstReaderInit(xc);
+
+ if ((rc) && (xc->vc_section_count) && (xc->maxhandle) &&
+ ((xc->fh) || (xc->contains_hier_section || (xc->contains_hier_section_lz4)))) {
+ /* more init */
+ xc->do_rewind = 1;
+ } else {
+ fstReaderClose(xc);
+ xc = NULL;
+ }
+ }
+
+ return (xc);
+}
+
+static void fstReaderDeallocateRvatData(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ if (xc) {
+ free(xc->rvat_chain_mem);
+ xc->rvat_chain_mem = NULL;
+ free(xc->rvat_frame_data);
+ xc->rvat_frame_data = NULL;
+ free(xc->rvat_time_table);
+ xc->rvat_time_table = NULL;
+ free(xc->rvat_chain_table);
+ xc->rvat_chain_table = NULL;
+ free(xc->rvat_chain_table_lengths);
+ xc->rvat_chain_table_lengths = NULL;
+
+ xc->rvat_data_valid = 0;
+ }
+}
+
+void fstReaderClose(void *ctx)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ if (xc) {
+ fstReaderDeallocateScopeData(xc);
+ fstReaderDeallocateRvatData(xc);
+ free(xc->rvat_sig_offs);
+ xc->rvat_sig_offs = NULL;
+
+ free(xc->process_mask);
+ xc->process_mask = NULL;
+ free(xc->blackout_times);
+ xc->blackout_times = NULL;
+ free(xc->blackout_activity);
+ xc->blackout_activity = NULL;
+ free(xc->temp_signal_value_buf);
+ xc->temp_signal_value_buf = NULL;
+ free(xc->signal_typs);
+ xc->signal_typs = NULL;
+ free(xc->signal_lens);
+ xc->signal_lens = NULL;
+ free(xc->filename);
+ xc->filename = NULL;
+
+ if (xc->fh) {
+ tmpfile_close(&xc->fh, &xc->fh_nam);
+ }
+
+ if (xc->f) {
+ tmpfile_close(&xc->f, &xc->f_nam);
+ if (xc->filename_unpacked) {
+ unlink(xc->filename_unpacked);
+ free(xc->filename_unpacked);
+ }
+ }
+
+ free(xc);
+ }
+}
+
+/*
+ * read processing
+ */
+
+/* normal read which re-interleaves the value change data */
+int fstReaderIterBlocks(void *ctx,
+ void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx,
+ const unsigned char *value),
+ void *user_callback_data_pointer, FILE *fv)
+{
+ return (fstReaderIterBlocks2(ctx, value_change_callback, NULL, user_callback_data_pointer, fv));
+}
+
+int fstReaderIterBlocks2(void *ctx,
+ void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time,
+ fstHandle facidx, const unsigned char *value),
+ void (*value_change_callback_varlen)(void *user_callback_data_pointer, uint64_t time,
+ fstHandle facidx, const unsigned char *value,
+ uint32_t len),
+ void *user_callback_data_pointer, FILE *fv)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+
+ uint64_t previous_time = UINT64_MAX;
+ uint64_t *time_table = NULL;
+ uint64_t tsec_nitems;
+ unsigned int secnum = 0;
+ int blocks_skipped = 0;
+ fst_off_t blkpos = 0;
+ uint64_t seclen, beg_tim;
+ uint64_t end_tim;
+ uint64_t frame_uclen, frame_clen, frame_maxhandle, vc_maxhandle;
+ fst_off_t vc_start;
+ fst_off_t indx_pntr, indx_pos;
+ fst_off_t *chain_table = NULL;
+ uint32_t *chain_table_lengths = NULL;
+ unsigned char *chain_cmem;
+ unsigned char *pnt;
+ long chain_clen;
+ fstHandle idx, pidx = 0, i;
+ uint64_t pval;
+ uint64_t vc_maxhandle_largest = 0;
+ uint64_t tsec_uclen = 0, tsec_clen = 0;
+ int sectype;
+ uint64_t mem_required_for_traversal;
+ unsigned char *mem_for_traversal = NULL;
+ uint32_t traversal_mem_offs;
+ uint32_t *scatterptr, *headptr, *length_remaining;
+ uint32_t cur_blackout = 0;
+ int packtype;
+ unsigned char *mc_mem = NULL;
+ uint32_t mc_mem_len; /* corresponds to largest value encountered in chain_table_lengths[i] */
+ int dumpvars_state = 0;
+
+ if (!xc)
+ return (0);
+
+ scatterptr = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t));
+ headptr = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t));
+ length_remaining = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t));
+
+ if (fv) {
+#ifndef FST_WRITEX_DISABLE
+ fflush(fv);
+ setvbuf(fv, (char *)NULL, _IONBF,
+ 0); /* even buffered IO is slow so disable it and use our own routines that don't need seeking */
+ xc->writex_fd = fileno(fv);
+#endif
+ }
+
+ for (;;) {
+ uint32_t *tc_head = NULL;
+ traversal_mem_offs = 0;
+
+ fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET);
+
+ sectype = fgetc(xc->f);
+ seclen = fstReaderUint64(xc->f);
+
+ if ((sectype == EOF) || (sectype == FST_BL_SKIP)) {
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "<< EOF >>\n");
+#endif
+ break;
+ }
+
+ blkpos++;
+ if ((sectype != FST_BL_VCDATA) && (sectype != FST_BL_VCDATA_DYN_ALIAS) &&
+ (sectype != FST_BL_VCDATA_DYN_ALIAS2)) {
+ blkpos += seclen;
+ continue;
+ }
+
+ if (!seclen)
+ break;
+
+ beg_tim = fstReaderUint64(xc->f);
+ end_tim = fstReaderUint64(xc->f);
+
+ if (xc->limit_range_valid) {
+ if (end_tim < xc->limit_range_start) {
+ blocks_skipped++;
+ blkpos += seclen;
+ continue;
+ }
+
+ if (beg_tim >
+ xc->limit_range_end) /* likely the compare in for(i=0;i<tsec_nitems;i++) below would do this earlier */
+ {
+ break;
+ }
+ }
+
+ mem_required_for_traversal = fstReaderUint64(xc->f);
+ mem_for_traversal =
+ (unsigned char *)malloc(mem_required_for_traversal + 66); /* add in potential fastlz overhead */
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "sec: %u seclen: %d begtim: %d endtim: %d\n", secnum, (int)seclen, (int)beg_tim,
+ (int)end_tim);
+ fprintf(stderr, FST_APIMESS "mem_required_for_traversal: %d\n", (int)mem_required_for_traversal);
+#endif
+ /* process time block */
+ {
+ unsigned char *ucdata;
+ unsigned char *cdata;
+ unsigned long destlen /* = tsec_uclen */; /* scan-build */
+ unsigned long sourcelen /*= tsec_clen */; /* scan-build */
+ int rc;
+ unsigned char *tpnt;
+ uint64_t tpval;
+ unsigned int ti;
+
+ if (fstReaderFseeko(xc, xc->f, blkpos + seclen - 24, SEEK_SET) != 0)
+ break;
+ tsec_uclen = fstReaderUint64(xc->f);
+ tsec_clen = fstReaderUint64(xc->f);
+ tsec_nitems = fstReaderUint64(xc->f);
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "time section unc: %d, com: %d (%d items)\n", (int)tsec_uclen, (int)tsec_clen,
+ (int)tsec_nitems);
+#endif
+ if (tsec_clen > seclen)
+ break; /* corrupted tsec_clen: by definition it can't be larger than size of section */
+ ucdata = (unsigned char *)malloc(tsec_uclen);
+ if (!ucdata)
+ break; /* malloc fail as tsec_uclen out of range from corrupted file */
+ destlen = tsec_uclen;
+ sourcelen = tsec_clen;
+
+ fstReaderFseeko(xc, xc->f, -24 - ((fst_off_t)tsec_clen), SEEK_CUR);
+
+ if (tsec_uclen != tsec_clen) {
+ cdata = (unsigned char *)malloc(tsec_clen);
+ fstFread(cdata, tsec_clen, 1, xc->f);
+
+ rc = uncompress(ucdata, &destlen, cdata, sourcelen);
+
+ if (rc != Z_OK) {
+ fprintf(stderr, FST_APIMESS "fstReaderIterBlocks2(), tsec uncompress rc = %d, exiting.\n", rc);
+ exit(255);
+ }
+
+ free(cdata);
+ } else {
+ fstFread(ucdata, tsec_uclen, 1, xc->f);
+ }
+
+ free(time_table);
+ time_table = (uint64_t *)calloc(tsec_nitems, sizeof(uint64_t));
+ tpnt = ucdata;
+ tpval = 0;
+ for (ti = 0; ti < tsec_nitems; ti++) {
+ int skiplen;
+ uint64_t val = fstGetVarint64(tpnt, &skiplen);
+ tpval = time_table[ti] = tpval + val;
+ tpnt += skiplen;
+ }
+
+ tc_head = (uint32_t *)calloc(tsec_nitems /* scan-build */ ? tsec_nitems : 1, sizeof(uint32_t));
+ free(ucdata);
+ }
+
+ fstReaderFseeko(xc, xc->f, blkpos + 32, SEEK_SET);
+
+ frame_uclen = fstReaderVarint64(xc->f);
+ frame_clen = fstReaderVarint64(xc->f);
+ frame_maxhandle = fstReaderVarint64(xc->f);
+
+ if (secnum == 0) {
+ if ((beg_tim != time_table[0]) || (blocks_skipped)) {
+ unsigned char *mu = (unsigned char *)malloc(frame_uclen);
+ uint32_t sig_offs = 0;
+
+ if (fv) {
+ char wx_buf[32];
+ int wx_len;
+
+ if (beg_tim) {
+ if (dumpvars_state == 1) {
+ wx_len = sprintf(wx_buf, "$end\n");
+ fstWritex(xc, wx_buf, wx_len);
+ dumpvars_state = 2;
+ }
+ wx_len = sprintf(wx_buf, "#%" PRIu64 "\n", beg_tim);
+ fstWritex(xc, wx_buf, wx_len);
+ if (!dumpvars_state) {
+ wx_len = sprintf(wx_buf, "$dumpvars\n");
+ fstWritex(xc, wx_buf, wx_len);
+ dumpvars_state = 1;
+ }
+ }
+ if ((xc->num_blackouts) && (cur_blackout != xc->num_blackouts)) {
+ if (beg_tim == xc->blackout_times[cur_blackout]) {
+ wx_len = sprintf(wx_buf, "$dump%s $end\n",
+ (xc->blackout_activity[cur_blackout++]) ? "on" : "off");
+ fstWritex(xc, wx_buf, wx_len);
+ }
+ }
+ }
+
+ if (frame_uclen == frame_clen) {
+ fstFread(mu, frame_uclen, 1, xc->f);
+ } else {
+ unsigned char *mc = (unsigned char *)malloc(frame_clen);
+ int rc;
+
+ unsigned long destlen = frame_uclen;
+ unsigned long sourcelen = frame_clen;
+
+ fstFread(mc, sourcelen, 1, xc->f);
+ rc = uncompress(mu, &destlen, mc, sourcelen);
+ if (rc != Z_OK) {
+ fprintf(stderr, FST_APIMESS "fstReaderIterBlocks2(), frame uncompress rc: %d, exiting.\n", rc);
+ exit(255);
+ }
+ free(mc);
+ }
+
+ for (idx = 0; idx < frame_maxhandle; idx++) {
+ int process_idx = idx / 8;
+ int process_bit = idx & 7;
+
+ if (xc->process_mask[process_idx] & (1 << process_bit)) {
+ if (xc->signal_lens[idx] <= 1) {
+ if (xc->signal_lens[idx] == 1) {
+ unsigned char val = mu[sig_offs];
+ if (value_change_callback) {
+ xc->temp_signal_value_buf[0] = val;
+ xc->temp_signal_value_buf[1] = 0;
+ value_change_callback(user_callback_data_pointer, beg_tim, idx + 1,
+ xc->temp_signal_value_buf);
+ } else {
+ if (fv) {
+ char vcd_id[16];
+
+ int vcdid_len = fstVcdIDForFwrite(vcd_id + 1, idx + 1);
+ vcd_id[0] = val; /* collapse 3 writes into one I/O call */
+ vcd_id[vcdid_len + 1] = '\n';
+ fstWritex(xc, vcd_id, vcdid_len + 2);
+ }
+ }
+ } else {
+ /* variable-length ("0" length) records have no initial state */
+ }
+ } else {
+ if (xc->signal_typs[idx] != FST_VT_VCD_REAL) {
+ if (value_change_callback) {
+ memcpy(xc->temp_signal_value_buf, mu + sig_offs, xc->signal_lens[idx]);
+ xc->temp_signal_value_buf[xc->signal_lens[idx]] = 0;
+ value_change_callback(user_callback_data_pointer, beg_tim, idx + 1,
+ xc->temp_signal_value_buf);
+ } else {
+ if (fv) {
+ char vcd_id[16];
+ int vcdid_len = fstVcdIDForFwrite(vcd_id + 1, idx + 1);
+
+ vcd_id[0] = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p';
+ fstWritex(xc, vcd_id, 1);
+ fstWritex(xc, mu + sig_offs, xc->signal_lens[idx]);
+
+ vcd_id[0] = ' '; /* collapse 3 writes into one I/O call */
+ vcd_id[vcdid_len + 1] = '\n';
+ fstWritex(xc, vcd_id, vcdid_len + 2);
+ }
+ }
+ } else {
+ double d;
+ unsigned char *clone_d;
+ unsigned char *srcdata = mu + sig_offs;
+
+ if (value_change_callback) {
+ if (xc->native_doubles_for_cb) {
+ if (xc->double_endian_match) {
+ clone_d = srcdata;
+ } else {
+ int j;
+
+ clone_d = (unsigned char *)&d;
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+ value_change_callback(user_callback_data_pointer, beg_tim, idx + 1, clone_d);
+ } else {
+ clone_d = (unsigned char *)&d;
+ if (xc->double_endian_match) {
+ memcpy(clone_d, srcdata, 8);
+ } else {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+ sprintf((char *)xc->temp_signal_value_buf, "%.16g", d);
+ value_change_callback(user_callback_data_pointer, beg_tim, idx + 1,
+ xc->temp_signal_value_buf);
+ }
+ } else {
+ if (fv) {
+ char vcdid_buf[16];
+ char wx_buf[64];
+ int wx_len;
+
+ clone_d = (unsigned char *)&d;
+ if (xc->double_endian_match) {
+ memcpy(clone_d, srcdata, 8);
+ } else {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+
+ fstVcdID(vcdid_buf, idx + 1);
+ wx_len = sprintf(wx_buf, "r%.16g %s\n", d, vcdid_buf);
+ fstWritex(xc, wx_buf, wx_len);
+ }
+ }
+ }
+ }
+ }
+
+ sig_offs += xc->signal_lens[idx];
+ }
+
+ free(mu);
+ fstReaderFseeko(xc, xc->f, -((fst_off_t)frame_clen), SEEK_CUR);
+ }
+ }
+
+ fstReaderFseeko(xc, xc->f, (fst_off_t)frame_clen, SEEK_CUR); /* skip past compressed data */
+
+ vc_maxhandle = fstReaderVarint64(xc->f);
+ vc_start = ftello(xc->f); /* points to '!' character */
+ packtype = fgetc(xc->f);
+
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "frame_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", (int)frame_uclen,
+ (int)frame_clen, (int)frame_maxhandle);
+ fprintf(stderr, FST_APIMESS "vc_maxhandle: %d, packtype: %c\n", (int)vc_maxhandle, packtype);
+#endif
+
+ indx_pntr = blkpos + seclen - 24 - tsec_clen - 8;
+ fstReaderFseeko(xc, xc->f, indx_pntr, SEEK_SET);
+ chain_clen = fstReaderUint64(xc->f);
+ indx_pos = indx_pntr - chain_clen;
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen);
+#endif
+ chain_cmem = (unsigned char *)malloc(chain_clen);
+ if (!chain_cmem)
+ goto block_err;
+ fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET);
+ fstFread(chain_cmem, chain_clen, 1, xc->f);
+
+ if (vc_maxhandle > vc_maxhandle_largest) {
+ free(chain_table);
+ free(chain_table_lengths);
+
+ vc_maxhandle_largest = vc_maxhandle;
+ chain_table = (fst_off_t *)calloc((vc_maxhandle + 1), sizeof(fst_off_t));
+ chain_table_lengths = (uint32_t *)calloc((vc_maxhandle + 1), sizeof(uint32_t));
+ }
+
+ if (!chain_table || !chain_table_lengths)
+ goto block_err;
+
+ pnt = chain_cmem;
+ idx = 0;
+ pval = 0;
+
+ if (sectype == FST_BL_VCDATA_DYN_ALIAS2) {
+ uint32_t prev_alias = 0;
+
+ do {
+ int skiplen;
+
+ if (*pnt & 0x01) {
+ int64_t shval = fstGetSVarint64(pnt, &skiplen) >> 1;
+ if (shval > 0) {
+ pval = chain_table[idx] = pval + shval;
+ if (idx) {
+ chain_table_lengths[pidx] = pval - chain_table[pidx];
+ }
+ pidx = idx++;
+ } else if (shval < 0) {
+ chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */
+ chain_table_lengths[idx] = prev_alias =
+ shval; /* because during this loop iter would give stale data! */
+ idx++;
+ } else {
+ chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */
+ chain_table_lengths[idx] =
+ prev_alias; /* because during this loop iter would give stale data! */
+ idx++;
+ }
+ } else {
+ uint64_t val = fstGetVarint32(pnt, &skiplen);
+
+ fstHandle loopcnt = val >> 1;
+ for (i = 0; i < loopcnt; i++) {
+ chain_table[idx++] = 0;
+ }
+ }
+
+ pnt += skiplen;
+ } while (pnt != (chain_cmem + chain_clen));
+ } else {
+ do {
+ int skiplen;
+ uint64_t val = fstGetVarint32(pnt, &skiplen);
+
+ if (!val) {
+ pnt += skiplen;
+ val = fstGetVarint32(pnt, &skiplen);
+ chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */
+ chain_table_lengths[idx] = -val; /* because during this loop iter would give stale data! */
+ idx++;
+ } else if (val & 1) {
+ pval = chain_table[idx] = pval + (val >> 1);
+ if (idx) {
+ chain_table_lengths[pidx] = pval - chain_table[pidx];
+ }
+ pidx = idx++;
+ } else {
+ fstHandle loopcnt = val >> 1;
+ for (i = 0; i < loopcnt; i++) {
+ chain_table[idx++] = 0;
+ }
+ }
+
+ pnt += skiplen;
+ } while (pnt != (chain_cmem + chain_clen));
+ }
+
+ chain_table[idx] = indx_pos - vc_start;
+ chain_table_lengths[pidx] = chain_table[idx] - chain_table[pidx];
+
+ for (i = 0; i < idx; i++) {
+ int32_t v32 = chain_table_lengths[i];
+ if ((v32 < 0) && (!chain_table[i])) {
+ v32 = -v32;
+ v32--;
+ if (((uint32_t)v32) < i) /* sanity check */
+ {
+ chain_table[i] = chain_table[v32];
+ chain_table_lengths[i] = chain_table_lengths[v32];
+ }
+ }
+ }
+
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "decompressed chain idx len: %" PRIu32 "\n", idx);
+#endif
+
+ mc_mem_len = 16384;
+ mc_mem = (unsigned char *)malloc(mc_mem_len); /* buffer for compressed reads */
+
+ /* check compressed VC data */
+ if (idx > xc->maxhandle)
+ idx = xc->maxhandle;
+ for (i = 0; i < idx; i++) {
+ if (chain_table[i]) {
+ int process_idx = i / 8;
+ int process_bit = i & 7;
+
+ if (xc->process_mask[process_idx] & (1 << process_bit)) {
+ int rc = Z_OK;
+ uint32_t val;
+ uint32_t skiplen;
+ uint32_t tdelta;
+
+ fstReaderFseeko(xc, xc->f, vc_start + chain_table[i], SEEK_SET);
+ val = fstReaderVarint32WithSkip(xc->f, &skiplen);
+ if (val) {
+ unsigned char *mu = mem_for_traversal + traversal_mem_offs; /* uncomp: dst */
+ unsigned char *mc; /* comp: src */
+ unsigned long destlen = val;
+ unsigned long sourcelen = chain_table_lengths[i];
+
+ if (mc_mem_len < chain_table_lengths[i]) {
+ free(mc_mem);
+ mc_mem = (unsigned char *)malloc(mc_mem_len = chain_table_lengths[i]);
+ }
+ mc = mc_mem;
+
+ fstFread(mc, chain_table_lengths[i], 1, xc->f);
+
+ switch (packtype) {
+ case '4':
+ rc = (destlen == (unsigned long)LZ4_decompress_safe_partial((char *)mc, (char *)mu,
+ sourcelen, destlen, destlen))
+ ? Z_OK
+ : Z_DATA_ERROR;
+ break;
+ case 'F':
+ fastlz_decompress(mc, sourcelen, mu, destlen); /* rc appears unreliable */
+ break;
+ default:
+ rc = uncompress(mu, &destlen, mc, sourcelen);
+ break;
+ }
+
+ /* data to process is for(j=0;j<destlen;j++) in mu[j] */
+ headptr[i] = traversal_mem_offs;
+ length_remaining[i] = val;
+ traversal_mem_offs += val;
+ } else {
+ int destlen = chain_table_lengths[i] - skiplen;
+ unsigned char *mu = mem_for_traversal + traversal_mem_offs;
+ fstFread(mu, destlen, 1, xc->f);
+ /* data to process is for(j=0;j<destlen;j++) in mu[j] */
+ headptr[i] = traversal_mem_offs;
+ length_remaining[i] = destlen;
+ traversal_mem_offs += destlen;
+ }
+
+ if (rc != Z_OK) {
+ fprintf(stderr, FST_APIMESS "fstReaderIterBlocks2(), fac: %d clen: %d (rc=%d), exiting.\n",
+ (int)i, (int)val, rc);
+ exit(255);
+ }
+
+ if (xc->signal_lens[i] == 1) {
+ uint32_t vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[i]);
+ uint32_t shcnt = 2 << (vli & 1);
+ tdelta = vli >> shcnt;
+ } else {
+ uint32_t vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[i]);
+ tdelta = vli >> 1;
+ }
+
+ scatterptr[i] = tc_head[tdelta];
+ tc_head[tdelta] = i + 1;
+ }
+ }
+ }
+
+ free(mc_mem); /* there is no usage below for this, no real need to clear out mc_mem or mc_mem_len */
+
+ for (i = 0; i < tsec_nitems; i++) {
+ uint32_t tdelta;
+ int skiplen, skiplen2;
+ uint32_t vli;
+
+ if (fv) {
+ char wx_buf[32];
+ int wx_len;
+
+ if (time_table[i] != previous_time) {
+ if (xc->limit_range_valid) {
+ if (time_table[i] > xc->limit_range_end) {
+ break;
+ }
+ }
+
+ if (dumpvars_state == 1) {
+ wx_len = sprintf(wx_buf, "$end\n");
+ fstWritex(xc, wx_buf, wx_len);
+ dumpvars_state = 2;
+ }
+ wx_len = sprintf(wx_buf, "#%" PRIu64 "\n", time_table[i]);
+ fstWritex(xc, wx_buf, wx_len);
+ if (!dumpvars_state) {
+ wx_len = sprintf(wx_buf, "$dumpvars\n");
+ fstWritex(xc, wx_buf, wx_len);
+ dumpvars_state = 1;
+ }
+
+ if ((xc->num_blackouts) && (cur_blackout != xc->num_blackouts)) {
+ if (time_table[i] == xc->blackout_times[cur_blackout]) {
+ wx_len = sprintf(wx_buf, "$dump%s $end\n",
+ (xc->blackout_activity[cur_blackout++]) ? "on" : "off");
+ fstWritex(xc, wx_buf, wx_len);
+ }
+ }
+ previous_time = time_table[i];
+ }
+ } else {
+ if (time_table[i] != previous_time) {
+ if (xc->limit_range_valid) {
+ if (time_table[i] > xc->limit_range_end) {
+ break;
+ }
+ }
+ previous_time = time_table[i];
+ }
+ }
+
+ while (tc_head[i]) {
+ idx = tc_head[i] - 1;
+ vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen);
+
+ if (xc->signal_lens[idx] <= 1) {
+ if (xc->signal_lens[idx] == 1) {
+ unsigned char val;
+ if (!(vli & 1)) {
+ /* tdelta = vli >> 2; */ /* scan-build */
+ val = ((vli >> 1) & 1) | '0';
+ } else {
+ /* tdelta = vli >> 4; */ /* scan-build */
+ val = FST_RCV_STR[((vli >> 1) & 7)];
+ }
+
+ if (value_change_callback) {
+ xc->temp_signal_value_buf[0] = val;
+ xc->temp_signal_value_buf[1] = 0;
+ value_change_callback(user_callback_data_pointer, time_table[i], idx + 1,
+ xc->temp_signal_value_buf);
+ } else {
+ if (fv) {
+ char vcd_id[16];
+ int vcdid_len = fstVcdIDForFwrite(vcd_id + 1, idx + 1);
+
+ vcd_id[0] = val;
+ vcd_id[vcdid_len + 1] = '\n';
+ fstWritex(xc, vcd_id, vcdid_len + 2);
+ }
+ }
+ headptr[idx] += skiplen;
+ length_remaining[idx] -= skiplen;
+
+ tc_head[i] = scatterptr[idx];
+ scatterptr[idx] = 0;
+
+ if (length_remaining[idx]) {
+ int shamt;
+ vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]);
+ shamt = 2 << (vli & 1);
+ tdelta = vli >> shamt;
+
+ scatterptr[idx] = tc_head[i + tdelta];
+ tc_head[i + tdelta] = idx + 1;
+ }
+ } else {
+ unsigned char *vdata;
+ uint32_t len;
+
+ vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen);
+ len = fstGetVarint32(mem_for_traversal + headptr[idx] + skiplen, &skiplen2);
+ /* tdelta = vli >> 1; */ /* scan-build */
+ skiplen += skiplen2;
+ vdata = mem_for_traversal + headptr[idx] + skiplen;
+
+ if (!(vli & 1)) {
+ if (value_change_callback_varlen) {
+ value_change_callback_varlen(user_callback_data_pointer, time_table[i], idx + 1, vdata,
+ len);
+ } else {
+ if (fv) {
+ char vcd_id[16];
+ int vcdid_len;
+
+ vcd_id[0] = 's';
+ fstWritex(xc, vcd_id, 1);
+
+ vcdid_len = fstVcdIDForFwrite(vcd_id + 1, idx + 1);
+ {
+ unsigned char *vesc = (unsigned char *)malloc(len * 4 + 1);
+ int vlen = fstUtilityBinToEsc(vesc, vdata, len);
+ fstWritex(xc, vesc, vlen);
+ free(vesc);
+ }
+
+ vcd_id[0] = ' ';
+ vcd_id[vcdid_len + 1] = '\n';
+ fstWritex(xc, vcd_id, vcdid_len + 2);
+ }
+ }
+ }
+
+ skiplen += len;
+ headptr[idx] += skiplen;
+ length_remaining[idx] -= skiplen;
+
+ tc_head[i] = scatterptr[idx];
+ scatterptr[idx] = 0;
+
+ if (length_remaining[idx]) {
+ vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]);
+ tdelta = vli >> 1;
+
+ scatterptr[idx] = tc_head[i + tdelta];
+ tc_head[i + tdelta] = idx + 1;
+ }
+ }
+ } else {
+ uint32_t len = xc->signal_lens[idx];
+ unsigned char *vdata;
+
+ vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen);
+ /* tdelta = vli >> 1; */ /* scan-build */
+ vdata = mem_for_traversal + headptr[idx] + skiplen;
+
+ if (xc->signal_typs[idx] != FST_VT_VCD_REAL) {
+ if (!(vli & 1)) {
+ int byte = 0;
+ int bit;
+ unsigned int j;
+
+ for (j = 0; j < len; j++) {
+ unsigned char ch;
+ byte = j / 8;
+ bit = 7 - (j & 7);
+ ch = ((vdata[byte] >> bit) & 1) | '0';
+ xc->temp_signal_value_buf[j] = ch;
+ }
+ xc->temp_signal_value_buf[j] = 0;
+
+ if (value_change_callback) {
+ value_change_callback(user_callback_data_pointer, time_table[i], idx + 1,
+ xc->temp_signal_value_buf);
+ } else {
+ if (fv) {
+ unsigned char ch_bp = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p';
+
+ fstWritex(xc, &ch_bp, 1);
+ fstWritex(xc, xc->temp_signal_value_buf, len);
+ }
+ }
+
+ len = byte + 1;
+ } else {
+ if (value_change_callback) {
+ memcpy(xc->temp_signal_value_buf, vdata, len);
+ xc->temp_signal_value_buf[len] = 0;
+ value_change_callback(user_callback_data_pointer, time_table[i], idx + 1,
+ xc->temp_signal_value_buf);
+ } else {
+ if (fv) {
+ unsigned char ch_bp = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p';
+
+ fstWritex(xc, &ch_bp, 1);
+ fstWritex(xc, vdata, len);
+ }
+ }
+ }
+ } else {
+ double d;
+ unsigned char *clone_d /*= (unsigned char *)&d */; /* scan-build */
+ unsigned char buf[8];
+ unsigned char *srcdata;
+
+ if (!(vli & 1)) /* very rare case, but possible */
+ {
+ int bit;
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ unsigned char ch;
+ bit = 7 - (j & 7);
+ ch = ((vdata[0] >> bit) & 1) | '0';
+ buf[j] = ch;
+ }
+
+ len = 1;
+ srcdata = buf;
+ } else {
+ srcdata = vdata;
+ }
+
+ if (value_change_callback) {
+ if (xc->native_doubles_for_cb) {
+ if (xc->double_endian_match) {
+ clone_d = srcdata;
+ } else {
+ int j;
+
+ clone_d = (unsigned char *)&d;
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+ value_change_callback(user_callback_data_pointer, time_table[i], idx + 1, clone_d);
+ } else {
+ clone_d = (unsigned char *)&d;
+ if (xc->double_endian_match) {
+ memcpy(clone_d, srcdata, 8);
+ } else {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+ sprintf((char *)xc->temp_signal_value_buf, "%.16g", d);
+ value_change_callback(user_callback_data_pointer, time_table[i], idx + 1,
+ xc->temp_signal_value_buf);
+ }
+ } else {
+ if (fv) {
+ char wx_buf[32];
+ int wx_len;
+
+ clone_d = (unsigned char *)&d;
+ if (xc->double_endian_match) {
+ memcpy(clone_d, srcdata, 8);
+ } else {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+
+ wx_len = sprintf(wx_buf, "r%.16g", d);
+ fstWritex(xc, wx_buf, wx_len);
+ }
+ }
+ }
+
+ if (fv) {
+ char vcd_id[16];
+ int vcdid_len = fstVcdIDForFwrite(vcd_id + 1, idx + 1);
+ vcd_id[0] = ' ';
+ vcd_id[vcdid_len + 1] = '\n';
+ fstWritex(xc, vcd_id, vcdid_len + 2);
+ }
+
+ skiplen += len;
+ headptr[idx] += skiplen;
+ length_remaining[idx] -= skiplen;
+
+ tc_head[i] = scatterptr[idx];
+ scatterptr[idx] = 0;
+
+ if (length_remaining[idx]) {
+ vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]);
+ tdelta = vli >> 1;
+
+ scatterptr[idx] = tc_head[i + tdelta];
+ tc_head[i + tdelta] = idx + 1;
+ }
+ }
+ }
+ }
+
+ block_err:
+ free(tc_head);
+ free(chain_cmem);
+ free(mem_for_traversal);
+ mem_for_traversal = NULL;
+
+ secnum++;
+ if (secnum == xc->vc_section_count)
+ break; /* in case file is growing, keep with original block count */
+ blkpos += seclen;
+ }
+
+ if (mem_for_traversal)
+ free(mem_for_traversal); /* scan-build */
+ free(length_remaining);
+ free(headptr);
+ free(scatterptr);
+
+ if (chain_table)
+ free(chain_table);
+ if (chain_table_lengths)
+ free(chain_table_lengths);
+
+ free(time_table);
+
+#ifndef FST_WRITEX_DISABLE
+ if (fv) {
+ fstWritex(xc, NULL, 0);
+ }
+#endif
+
+ return (1);
+}
+
+/* rvat functions */
+
+static char *fstExtractRvatDataFromFrame(struct fstReaderContext *xc, fstHandle facidx, char *buf)
+{
+ if (facidx >= xc->rvat_frame_maxhandle) {
+ return (NULL);
+ }
+
+ if (xc->signal_lens[facidx] == 1) {
+ buf[0] = (char)xc->rvat_frame_data[xc->rvat_sig_offs[facidx]];
+ buf[1] = 0;
+ } else {
+ if (xc->signal_typs[facidx] != FST_VT_VCD_REAL) {
+ memcpy(buf, xc->rvat_frame_data + xc->rvat_sig_offs[facidx], xc->signal_lens[facidx]);
+ buf[xc->signal_lens[facidx]] = 0;
+ } else {
+ double d;
+ unsigned char *clone_d = (unsigned char *)&d;
+ unsigned char *srcdata = xc->rvat_frame_data + xc->rvat_sig_offs[facidx];
+
+ if (xc->double_endian_match) {
+ memcpy(clone_d, srcdata, 8);
+ } else {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+
+ sprintf((char *)buf, "%.16g", d);
+ }
+ }
+
+ return (buf);
+}
+
+char *fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf)
+{
+ struct fstReaderContext *xc = (struct fstReaderContext *)ctx;
+ fst_off_t blkpos = 0, prev_blkpos;
+ uint64_t beg_tim, end_tim, beg_tim2, end_tim2;
+ int sectype;
+ unsigned int secnum = 0;
+ uint64_t seclen;
+ uint64_t tsec_uclen = 0, tsec_clen = 0;
+ uint64_t tsec_nitems;
+ uint64_t frame_uclen, frame_clen;
+#ifdef FST_DEBUG
+ uint64_t mem_required_for_traversal;
+#endif
+ fst_off_t indx_pntr, indx_pos;
+ long chain_clen;
+ unsigned char *chain_cmem;
+ unsigned char *pnt;
+ fstHandle idx, pidx = 0, i;
+ uint64_t pval;
+
+ if ((!xc) || (!facidx) || (facidx > xc->maxhandle) || (!buf) || (!xc->signal_lens[facidx - 1])) {
+ return (NULL);
+ }
+
+ if (!xc->rvat_sig_offs) {
+ uint32_t cur_offs = 0;
+
+ xc->rvat_sig_offs = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t));
+ for (i = 0; i < xc->maxhandle; i++) {
+ xc->rvat_sig_offs[i] = cur_offs;
+ cur_offs += xc->signal_lens[i];
+ }
+ }
+
+ if (xc->rvat_data_valid) {
+ if ((xc->rvat_beg_tim <= tim) && (tim <= xc->rvat_end_tim)) {
+ goto process_value;
+ }
+
+ fstReaderDeallocateRvatData(xc);
+ }
+
+ xc->rvat_chain_pos_valid = 0;
+
+ for (;;) {
+ fstReaderFseeko(xc, xc->f, (prev_blkpos = blkpos), SEEK_SET);
+
+ sectype = fgetc(xc->f);
+ seclen = fstReaderUint64(xc->f);
+
+ if ((sectype == EOF) || (sectype == FST_BL_SKIP) || (!seclen)) {
+ return (NULL); /* if this loop exits on break, it's successful */
+ }
+
+ blkpos++;
+ if ((sectype != FST_BL_VCDATA) && (sectype != FST_BL_VCDATA_DYN_ALIAS) &&
+ (sectype != FST_BL_VCDATA_DYN_ALIAS2)) {
+ blkpos += seclen;
+ continue;
+ }
+
+ beg_tim = fstReaderUint64(xc->f);
+ end_tim = fstReaderUint64(xc->f);
+
+ if ((beg_tim <= tim) && (tim <= end_tim)) {
+ if ((tim == end_tim) && (tim != xc->end_time)) {
+ fst_off_t cached_pos = ftello(xc->f);
+ fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET);
+
+ sectype = fgetc(xc->f);
+ seclen = fstReaderUint64(xc->f);
+
+ beg_tim2 = fstReaderUint64(xc->f);
+ end_tim2 = fstReaderUint64(xc->f);
+
+ if (((sectype != FST_BL_VCDATA) && (sectype != FST_BL_VCDATA_DYN_ALIAS) &&
+ (sectype != FST_BL_VCDATA_DYN_ALIAS2)) ||
+ (!seclen) || (beg_tim2 != tim)) {
+ blkpos = prev_blkpos;
+ break;
+ }
+ beg_tim = beg_tim2;
+ end_tim = end_tim2;
+ fstReaderFseeko(xc, xc->f, cached_pos, SEEK_SET);
+ }
+ break;
+ }
+
+ blkpos += seclen;
+ secnum++;
+ }
+
+ xc->rvat_beg_tim = beg_tim;
+ xc->rvat_end_tim = end_tim;
+
+#ifdef FST_DEBUG
+ mem_required_for_traversal =
+#endif
+ fstReaderUint64(xc->f);
+
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "rvat sec: %u seclen: %d begtim: %d endtim: %d\n", secnum, (int)seclen, (int)beg_tim,
+ (int)end_tim);
+ fprintf(stderr, FST_APIMESS "mem_required_for_traversal: %d\n", (int)mem_required_for_traversal);
+#endif
+
+ /* process time block */
+ {
+ unsigned char *ucdata;
+ unsigned char *cdata;
+ unsigned long destlen /* = tsec_uclen */; /* scan-build */
+ unsigned long sourcelen /* = tsec_clen */; /* scan-build */
+ int rc;
+ unsigned char *tpnt;
+ uint64_t tpval;
+ unsigned int ti;
+
+ fstReaderFseeko(xc, xc->f, blkpos + seclen - 24, SEEK_SET);
+ tsec_uclen = fstReaderUint64(xc->f);
+ tsec_clen = fstReaderUint64(xc->f);
+ tsec_nitems = fstReaderUint64(xc->f);
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "time section unc: %d, com: %d (%d items)\n", (int)tsec_uclen, (int)tsec_clen,
+ (int)tsec_nitems);
+#endif
+ ucdata = (unsigned char *)malloc(tsec_uclen);
+ destlen = tsec_uclen;
+ sourcelen = tsec_clen;
+
+ fstReaderFseeko(xc, xc->f, -24 - ((fst_off_t)tsec_clen), SEEK_CUR);
+ if (tsec_uclen != tsec_clen) {
+ cdata = (unsigned char *)malloc(tsec_clen);
+ fstFread(cdata, tsec_clen, 1, xc->f);
+
+ rc = uncompress(ucdata, &destlen, cdata, sourcelen);
+
+ if (rc != Z_OK) {
+ fprintf(stderr, FST_APIMESS "fstReaderGetValueFromHandleAtTime(), tsec uncompress rc = %d, exiting.\n",
+ rc);
+ exit(255);
+ }
+
+ free(cdata);
+ } else {
+ fstFread(ucdata, tsec_uclen, 1, xc->f);
+ }
+
+ xc->rvat_time_table = (uint64_t *)calloc(tsec_nitems, sizeof(uint64_t));
+ tpnt = ucdata;
+ tpval = 0;
+ for (ti = 0; ti < tsec_nitems; ti++) {
+ int skiplen;
+ uint64_t val = fstGetVarint64(tpnt, &skiplen);
+ tpval = xc->rvat_time_table[ti] = tpval + val;
+ tpnt += skiplen;
+ }
+
+ free(ucdata);
+ }
+
+ fstReaderFseeko(xc, xc->f, blkpos + 32, SEEK_SET);
+
+ frame_uclen = fstReaderVarint64(xc->f);
+ frame_clen = fstReaderVarint64(xc->f);
+ xc->rvat_frame_maxhandle = fstReaderVarint64(xc->f);
+ xc->rvat_frame_data = (unsigned char *)malloc(frame_uclen);
+
+ if (frame_uclen == frame_clen) {
+ fstFread(xc->rvat_frame_data, frame_uclen, 1, xc->f);
+ } else {
+ unsigned char *mc = (unsigned char *)malloc(frame_clen);
+ int rc;
+
+ unsigned long destlen = frame_uclen;
+ unsigned long sourcelen = frame_clen;
+
+ fstFread(mc, sourcelen, 1, xc->f);
+ rc = uncompress(xc->rvat_frame_data, &destlen, mc, sourcelen);
+ if (rc != Z_OK) {
+ fprintf(stderr, FST_APIMESS "fstReaderGetValueFromHandleAtTime(), frame decompress rc: %d, exiting.\n", rc);
+ exit(255);
+ }
+ free(mc);
+ }
+
+ xc->rvat_vc_maxhandle = fstReaderVarint64(xc->f);
+ xc->rvat_vc_start = ftello(xc->f); /* points to '!' character */
+ xc->rvat_packtype = fgetc(xc->f);
+
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "frame_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", (int)frame_uclen,
+ (int)frame_clen, (int)xc->rvat_frame_maxhandle);
+ fprintf(stderr, FST_APIMESS "vc_maxhandle: %d\n", (int)xc->rvat_vc_maxhandle);
+#endif
+
+ indx_pntr = blkpos + seclen - 24 - tsec_clen - 8;
+ fstReaderFseeko(xc, xc->f, indx_pntr, SEEK_SET);
+ chain_clen = fstReaderUint64(xc->f);
+ indx_pos = indx_pntr - chain_clen;
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen);
+#endif
+ chain_cmem = (unsigned char *)malloc(chain_clen);
+ fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET);
+ fstFread(chain_cmem, chain_clen, 1, xc->f);
+
+ xc->rvat_chain_table = (fst_off_t *)calloc((xc->rvat_vc_maxhandle + 1), sizeof(fst_off_t));
+ xc->rvat_chain_table_lengths = (uint32_t *)calloc((xc->rvat_vc_maxhandle + 1), sizeof(uint32_t));
+
+ pnt = chain_cmem;
+ idx = 0;
+ pval = 0;
+
+ if (sectype == FST_BL_VCDATA_DYN_ALIAS2) {
+ uint32_t prev_alias = 0;
+
+ do {
+ int skiplen;
+
+ if (*pnt & 0x01) {
+ int64_t shval = fstGetSVarint64(pnt, &skiplen) >> 1;
+ if (shval > 0) {
+ pval = xc->rvat_chain_table[idx] = pval + shval;
+ if (idx) {
+ xc->rvat_chain_table_lengths[pidx] = pval - xc->rvat_chain_table[pidx];
+ }
+ pidx = idx++;
+ } else if (shval < 0) {
+ xc->rvat_chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */
+ xc->rvat_chain_table_lengths[idx] = prev_alias =
+ shval; /* because during this loop iter would give stale data! */
+ idx++;
+ } else {
+ xc->rvat_chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */
+ xc->rvat_chain_table_lengths[idx] =
+ prev_alias; /* because during this loop iter would give stale data! */
+ idx++;
+ }
+ } else {
+ uint64_t val = fstGetVarint32(pnt, &skiplen);
+
+ fstHandle loopcnt = val >> 1;
+ for (i = 0; i < loopcnt; i++) {
+ xc->rvat_chain_table[idx++] = 0;
+ }
+ }
+
+ pnt += skiplen;
+ } while (pnt != (chain_cmem + chain_clen));
+ } else {
+ do {
+ int skiplen;
+ uint64_t val = fstGetVarint32(pnt, &skiplen);
+
+ if (!val) {
+ pnt += skiplen;
+ val = fstGetVarint32(pnt, &skiplen);
+ xc->rvat_chain_table[idx] = 0;
+ xc->rvat_chain_table_lengths[idx] = -val;
+ idx++;
+ } else if (val & 1) {
+ pval = xc->rvat_chain_table[idx] = pval + (val >> 1);
+ if (idx) {
+ xc->rvat_chain_table_lengths[pidx] = pval - xc->rvat_chain_table[pidx];
+ }
+ pidx = idx++;
+ } else {
+ fstHandle loopcnt = val >> 1;
+ for (i = 0; i < loopcnt; i++) {
+ xc->rvat_chain_table[idx++] = 0;
+ }
+ }
+
+ pnt += skiplen;
+ } while (pnt != (chain_cmem + chain_clen));
+ }
+
+ free(chain_cmem);
+ xc->rvat_chain_table[idx] = indx_pos - xc->rvat_vc_start;
+ xc->rvat_chain_table_lengths[pidx] = xc->rvat_chain_table[idx] - xc->rvat_chain_table[pidx];
+
+ for (i = 0; i < idx; i++) {
+ int32_t v32 = xc->rvat_chain_table_lengths[i];
+ if ((v32 < 0) && (!xc->rvat_chain_table[i])) {
+ v32 = -v32;
+ v32--;
+ if (((uint32_t)v32) < i) /* sanity check */
+ {
+ xc->rvat_chain_table[i] = xc->rvat_chain_table[v32];
+ xc->rvat_chain_table_lengths[i] = xc->rvat_chain_table_lengths[v32];
+ }
+ }
+ }
+
+#ifdef FST_DEBUG
+ fprintf(stderr, FST_APIMESS "decompressed chain idx len: %" PRIu32 "\n", idx);
+#endif
+
+ xc->rvat_data_valid = 1;
+
+/* all data at this point is loaded or resident in fst cache, process and return appropriate value */
+process_value:
+ if (facidx > xc->rvat_vc_maxhandle) {
+ return (NULL);
+ }
+
+ facidx--; /* scale down for array which starts at zero */
+
+ if (((tim == xc->rvat_beg_tim) && (!xc->rvat_chain_table[facidx])) || (!xc->rvat_chain_table[facidx])) {
+ return (fstExtractRvatDataFromFrame(xc, facidx, buf));
+ }
+
+ if (facidx != xc->rvat_chain_facidx) {
+ if (xc->rvat_chain_mem) {
+ free(xc->rvat_chain_mem);
+ xc->rvat_chain_mem = NULL;
+
+ xc->rvat_chain_pos_valid = 0;
+ }
+ }
+
+ if (!xc->rvat_chain_mem) {
+ uint32_t skiplen;
+ fstReaderFseeko(xc, xc->f, xc->rvat_vc_start + xc->rvat_chain_table[facidx], SEEK_SET);
+ xc->rvat_chain_len = fstReaderVarint32WithSkip(xc->f, &skiplen);
+ if (xc->rvat_chain_len) {
+ unsigned char *mu = (unsigned char *)malloc(xc->rvat_chain_len);
+ unsigned char *mc = (unsigned char *)malloc(xc->rvat_chain_table_lengths[facidx]);
+ unsigned long destlen = xc->rvat_chain_len;
+ unsigned long sourcelen = xc->rvat_chain_table_lengths[facidx];
+ int rc = Z_OK;
+
+ fstFread(mc, xc->rvat_chain_table_lengths[facidx], 1, xc->f);
+
+ switch (xc->rvat_packtype) {
+ case '4':
+ rc = (destlen ==
+ (unsigned long)LZ4_decompress_safe_partial((char *)mc, (char *)mu, sourcelen, destlen, destlen))
+ ? Z_OK
+ : Z_DATA_ERROR;
+ break;
+ case 'F':
+ fastlz_decompress(mc, sourcelen, mu, destlen); /* rc appears unreliable */
+ break;
+ default:
+ rc = uncompress(mu, &destlen, mc, sourcelen);
+ break;
+ }
+
+ free(mc);
+
+ if (rc != Z_OK) {
+ fprintf(stderr,
+ FST_APIMESS "fstReaderGetValueFromHandleAtTime(), rvat decompress clen: %d (rc=%d), exiting.\n",
+ (int)xc->rvat_chain_len, rc);
+ exit(255);
+ }
+
+ /* data to process is for(j=0;j<destlen;j++) in mu[j] */
+ xc->rvat_chain_mem = mu;
+ } else {
+ int destlen = xc->rvat_chain_table_lengths[facidx] - skiplen;
+ unsigned char *mu = (unsigned char *)malloc(xc->rvat_chain_len = destlen);
+ fstFread(mu, destlen, 1, xc->f);
+ /* data to process is for(j=0;j<destlen;j++) in mu[j] */
+ xc->rvat_chain_mem = mu;
+ }
+
+ xc->rvat_chain_facidx = facidx;
+ }
+
+ /* process value chain here */
+
+ {
+ uint32_t tidx = 0, ptidx = 0;
+ uint32_t tdelta;
+ int skiplen;
+ unsigned int iprev = xc->rvat_chain_len;
+ uint32_t pvli = 0;
+ int pskip = 0;
+
+ if ((xc->rvat_chain_pos_valid) && (tim >= xc->rvat_chain_pos_time)) {
+ i = xc->rvat_chain_pos_idx;
+ tidx = xc->rvat_chain_pos_tidx;
+ } else {
+ i = 0;
+ tidx = 0;
+ xc->rvat_chain_pos_time = xc->rvat_beg_tim;
+ }
+
+ if (xc->signal_lens[facidx] == 1) {
+ while (i < xc->rvat_chain_len) {
+ uint32_t vli = fstGetVarint32(xc->rvat_chain_mem + i, &skiplen);
+ uint32_t shcnt = 2 << (vli & 1);
+ tdelta = vli >> shcnt;
+
+ if (xc->rvat_time_table[tidx + tdelta] <= tim) {
+ iprev = i;
+ pvli = vli;
+ ptidx = tidx;
+ /* pskip = skiplen; */ /* scan-build */
+
+ tidx += tdelta;
+ i += skiplen;
+ } else {
+ break;
+ }
+ }
+ if (iprev != xc->rvat_chain_len) {
+ xc->rvat_chain_pos_tidx = ptidx;
+ xc->rvat_chain_pos_idx = iprev;
+ xc->rvat_chain_pos_time = tim;
+ xc->rvat_chain_pos_valid = 1;
+
+ if (!(pvli & 1)) {
+ buf[0] = ((pvli >> 1) & 1) | '0';
+ } else {
+ buf[0] = FST_RCV_STR[((pvli >> 1) & 7)];
+ }
+ buf[1] = 0;
+ return (buf);
+ } else {
+ return (fstExtractRvatDataFromFrame(xc, facidx, buf));
+ }
+ } else {
+ while (i < xc->rvat_chain_len) {
+ uint32_t vli = fstGetVarint32(xc->rvat_chain_mem + i, &skiplen);
+ tdelta = vli >> 1;
+
+ if (xc->rvat_time_table[tidx + tdelta] <= tim) {
+ iprev = i;
+ pvli = vli;
+ ptidx = tidx;
+ pskip = skiplen;
+
+ tidx += tdelta;
+ i += skiplen;
+
+ if (!(pvli & 1)) {
+ i += ((xc->signal_lens[facidx] + 7) / 8);
+ } else {
+ i += xc->signal_lens[facidx];
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (iprev != xc->rvat_chain_len) {
+ unsigned char *vdata = xc->rvat_chain_mem + iprev + pskip;
+
+ xc->rvat_chain_pos_tidx = ptidx;
+ xc->rvat_chain_pos_idx = iprev;
+ xc->rvat_chain_pos_time = tim;
+ xc->rvat_chain_pos_valid = 1;
+
+ if (xc->signal_typs[facidx] != FST_VT_VCD_REAL) {
+ if (!(pvli & 1)) {
+ int byte = 0;
+ int bit;
+ unsigned int j;
+
+ for (j = 0; j < xc->signal_lens[facidx]; j++) {
+ unsigned char ch;
+ byte = j / 8;
+ bit = 7 - (j & 7);
+ ch = ((vdata[byte] >> bit) & 1) | '0';
+ buf[j] = ch;
+ }
+ buf[j] = 0;
+
+ return (buf);
+ } else {
+ memcpy(buf, vdata, xc->signal_lens[facidx]);
+ buf[xc->signal_lens[facidx]] = 0;
+ return (buf);
+ }
+ } else {
+ double d;
+ unsigned char *clone_d = (unsigned char *)&d;
+ unsigned char bufd[8];
+ unsigned char *srcdata;
+
+ if (!(pvli & 1)) /* very rare case, but possible */
+ {
+ int bit;
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ unsigned char ch;
+ bit = 7 - (j & 7);
+ ch = ((vdata[0] >> bit) & 1) | '0';
+ bufd[j] = ch;
+ }
+
+ srcdata = bufd;
+ } else {
+ srcdata = vdata;
+ }
+
+ if (xc->double_endian_match) {
+ memcpy(clone_d, srcdata, 8);
+ } else {
+ int j;
+
+ for (j = 0; j < 8; j++) {
+ clone_d[j] = srcdata[7 - j];
+ }
+ }
+
+ sprintf(buf, "r%.16g", d);
+ return (buf);
+ }
+ } else {
+ return (fstExtractRvatDataFromFrame(xc, facidx, buf));
+ }
+ }
+ }
+
+ /* return(NULL); */
+}
+
+/**********************************************************************/
+#ifndef _WAVE_HAVE_JUDY
+
+/***********************/
+/*** ***/
+/*** jenkins hash ***/
+/*** ***/
+/***********************/
+
+/*
+--------------------------------------------------------------------
+mix -- mix 3 32-bit values reversibly.
+For every delta with one or two bits set, and the deltas of all three
+ high bits or all three low bits, whether the original value of a,b,c
+ is almost all zero or is uniformly distributed,
+* If mix() is run forward or backward, at least 32 bits in a,b,c
+ have at least 1/4 probability of changing.
+* If mix() is run forward, every bit of c will change between 1/3 and
+ 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
+mix() was built out of 36 single-cycle latency instructions in a
+ structure that could supported 2x parallelism, like so:
+ a -= b;
+ a -= c; x = (c>>13);
+ b -= c; a ^= x;
+ b -= a; x = (a<<8);
+ c -= a; b ^= x;
+ c -= b; x = (b>>13);
+ ...
+ Unfortunately, superscalar Pentiums and Sparcs can't take advantage
+ of that parallelism. They've also turned some of those single-cycle
+ latency instructions into multi-cycle latency instructions. Still,
+ this is the fastest good hash I could find. There were about 2^^68
+ to choose from. I only looked at a billion or so.
+--------------------------------------------------------------------
+*/
+#define mix(a, b, c) \
+ { \
+ a -= b; \
+ a -= c; \
+ a ^= (c >> 13); \
+ b -= c; \
+ b -= a; \
+ b ^= (a << 8); \
+ c -= a; \
+ c -= b; \
+ c ^= (b >> 13); \
+ a -= b; \
+ a -= c; \
+ a ^= (c >> 12); \
+ b -= c; \
+ b -= a; \
+ b ^= (a << 16); \
+ c -= a; \
+ c -= b; \
+ c ^= (b >> 5); \
+ a -= b; \
+ a -= c; \
+ a ^= (c >> 3); \
+ b -= c; \
+ b -= a; \
+ b ^= (a << 10); \
+ c -= a; \
+ c -= b; \
+ c ^= (b >> 15); \
+ }
+
+/*
+--------------------------------------------------------------------
+j_hash() -- hash a variable-length key into a 32-bit value
+ k : the key (the unaligned variable-length array of bytes)
+ len : the length of the key, counting by bytes
+ initval : can be any 4-byte value
+Returns a 32-bit value. Every bit of the key affects every bit of
+the return value. Every 1-bit and 2-bit delta achieves avalanche.
+About 6*len+35 instructions.
+
+The best hash table sizes are powers of 2. There is no need to do
+mod a prime (mod is sooo slow!). If you need less than 32 bits,
+use a bitmask. For example, if you need only 10 bits, do
+ h = (h & hashmask(10));
+In which case, the hash table should have hashsize(10) elements.
+
+If you are hashing n strings (uint8_t **)k, do it like this:
+ for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
+
+By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
+code any way you wish, private, educational, or commercial. It's free.
+
+See http://burtleburtle.net/bob/hash/evahash.html
+Use for hash table lookup, or anything where one collision in 2^^32 is
+acceptable. Do NOT use for cryptographic purposes.
+--------------------------------------------------------------------
+*/
+
+static uint32_t j_hash(const uint8_t *k, uint32_t length, uint32_t initval)
+{
+ uint32_t a, b, c, len;
+
+ /* Set up the internal state */
+ len = length;
+ a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
+ c = initval; /* the previous hash value */
+
+ /*---------------------------------------- handle most of the key */
+ while (len >= 12) {
+ a += (k[0] + ((uint32_t)k[1] << 8) + ((uint32_t)k[2] << 16) + ((uint32_t)k[3] << 24));
+ b += (k[4] + ((uint32_t)k[5] << 8) + ((uint32_t)k[6] << 16) + ((uint32_t)k[7] << 24));
+ c += (k[8] + ((uint32_t)k[9] << 8) + ((uint32_t)k[10] << 16) + ((uint32_t)k[11] << 24));
+ mix(a, b, c);
+ k += 12;
+ len -= 12;
+ }
+
+ /*------------------------------------- handle the last 11 bytes */
+ c += length;
+ switch (len) /* all the case statements fall through */
+ {
+ case 11:
+ c += ((uint32_t)k[10] << 24); /* fallthrough */
+ case 10:
+ c += ((uint32_t)k[9] << 16); /* fallthrough */
+ case 9:
+ c += ((uint32_t)k[8] << 8); /* fallthrough */
+ /* the first byte of c is reserved for the length */
+ case 8:
+ b += ((uint32_t)k[7] << 24); /* fallthrough */
+ case 7:
+ b += ((uint32_t)k[6] << 16); /* fallthrough */
+ case 6:
+ b += ((uint32_t)k[5] << 8); /* fallthrough */
+ case 5:
+ b += k[4]; /* fallthrough */
+ case 4:
+ a += ((uint32_t)k[3] << 24); /* fallthrough */
+ case 3:
+ a += ((uint32_t)k[2] << 16); /* fallthrough */
+ case 2:
+ a += ((uint32_t)k[1] << 8); /* fallthrough */
+ case 1:
+ a += k[0];
+ /* case 0: nothing left to add */
+ }
+ mix(a, b, c);
+ /*-------------------------------------------- report the result */
+ return (c);
+}
+
+/********************************************************************/
+
+/***************************/
+/*** ***/
+/*** judy HS emulation ***/
+/*** ***/
+/***************************/
+
+struct collchain_t
+{
+ struct collchain_t *next;
+ void *payload;
+ uint32_t fullhash, length;
+ unsigned char mem[1];
+};
+
+void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint32_t hashmask)
+{
+ struct collchain_t ***base = (struct collchain_t ***)base_i;
+ uint32_t hf, h;
+ struct collchain_t **ar;
+ struct collchain_t *chain, *pchain;
+
+ if (!*base) {
+ *base = (struct collchain_t **)calloc(1, (hashmask + 1) * sizeof(void *));
+ }
+ ar = *base;
+
+ h = (hf = j_hash(mem, length, length)) & hashmask;
+ pchain = chain = ar[h];
+ while (chain) {
+ if ((chain->fullhash == hf) && (chain->length == length) && !memcmp(chain->mem, mem, length)) {
+ if (pchain != chain) /* move hit to front */
+ {
+ pchain->next = chain->next;
+ chain->next = ar[h];
+ ar[h] = chain;
+ }
+ return (&(chain->payload));
+ }
+
+ pchain = chain;
+ chain = chain->next;
+ }
+
+ chain = (struct collchain_t *)calloc(1, sizeof(struct collchain_t) + length - 1);
+ memcpy(chain->mem, mem, length);
+ chain->fullhash = hf;
+ chain->length = length;
+ chain->next = ar[h];
+ ar[h] = chain;
+ return (&(chain->payload));
+}
+
+void JenkinsFree(void *base_i, uint32_t hashmask)
+{
+ struct collchain_t ***base = (struct collchain_t ***)base_i;
+ uint32_t h;
+ struct collchain_t **ar;
+ struct collchain_t *chain, *chain_next;
+
+ if (base && *base) {
+ ar = *base;
+ for (h = 0; h <= hashmask; h++) {
+ chain = ar[h];
+ while (chain) {
+ chain_next = chain->next;
+ free(chain);
+ chain = chain_next;
+ }
+ }
+
+ free(*base);
+ *base = NULL;
+ }
+}
+
+#endif
+
+/**********************************************************************/
+
+/************************/
+/*** ***/
+/*** utility function ***/
+/*** ***/
+/************************/
+
+int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len)
+{
+ const unsigned char *src = s;
+ int dlen = 0;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ switch (src[i]) {
+ case '\a': /* fallthrough */
+ case '\b': /* fallthrough */
+ case '\f': /* fallthrough */
+ case '\n': /* fallthrough */
+ case '\r': /* fallthrough */
+ case '\t': /* fallthrough */
+ case '\v': /* fallthrough */
+ case '\'': /* fallthrough */
+ case '\"': /* fallthrough */
+ case '\\': /* fallthrough */
+ case '\?':
+ dlen += 2;
+ break;
+ default:
+ if ((src[i] > ' ') && (src[i] <= '~')) /* no white spaces in output */
+ {
+ dlen++;
+ } else {
+ dlen += 4;
+ }
+ break;
+ }
+ }
+
+ return (dlen);
+}
+
+int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len)
+{
+ const unsigned char *src = s;
+ unsigned char *dst = d;
+ unsigned char val;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ switch (src[i]) {
+ case '\a':
+ *(dst++) = '\\';
+ *(dst++) = 'a';
+ break;
+ case '\b':
+ *(dst++) = '\\';
+ *(dst++) = 'b';
+ break;
+ case '\f':
+ *(dst++) = '\\';
+ *(dst++) = 'f';
+ break;
+ case '\n':
+ *(dst++) = '\\';
+ *(dst++) = 'n';
+ break;
+ case '\r':
+ *(dst++) = '\\';
+ *(dst++) = 'r';
+ break;
+ case '\t':
+ *(dst++) = '\\';
+ *(dst++) = 't';
+ break;
+ case '\v':
+ *(dst++) = '\\';
+ *(dst++) = 'v';
+ break;
+ case '\'':
+ *(dst++) = '\\';
+ *(dst++) = '\'';
+ break;
+ case '\"':
+ *(dst++) = '\\';
+ *(dst++) = '\"';
+ break;
+ case '\\':
+ *(dst++) = '\\';
+ *(dst++) = '\\';
+ break;
+ case '\?':
+ *(dst++) = '\\';
+ *(dst++) = '\?';
+ break;
+ default:
+ if ((src[i] > ' ') && (src[i] <= '~')) /* no white spaces in output */
+ {
+ *(dst++) = src[i];
+ } else {
+ val = src[i];
+ *(dst++) = '\\';
+ *(dst++) = (val / 64) + '0';
+ val = val & 63;
+ *(dst++) = (val / 8) + '0';
+ val = val & 7;
+ *(dst++) = (val) + '0';
+ }
+ break;
+ }
+ }
+
+ return (dst - d);
+}
+
+/*
+ * this overwrites the original string if the destination pointer is NULL
+ */
+int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len)
+{
+ unsigned char *src = s;
+ unsigned char *dst = (!d) ? s : (s = d);
+ unsigned char val[3];
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (src[i] != '\\') {
+ *(dst++) = src[i];
+ } else {
+ switch (src[++i]) {
+ case 'a':
+ *(dst++) = '\a';
+ break;
+ case 'b':
+ *(dst++) = '\b';
+ break;
+ case 'f':
+ *(dst++) = '\f';
+ break;
+ case 'n':
+ *(dst++) = '\n';
+ break;
+ case 'r':
+ *(dst++) = '\r';
+ break;
+ case 't':
+ *(dst++) = '\t';
+ break;
+ case 'v':
+ *(dst++) = '\v';
+ break;
+ case '\'':
+ *(dst++) = '\'';
+ break;
+ case '\"':
+ *(dst++) = '\"';
+ break;
+ case '\\':
+ *(dst++) = '\\';
+ break;
+ case '\?':
+ *(dst++) = '\?';
+ break;
+
+ case 'x':
+ val[0] = toupper(src[++i]);
+ val[1] = toupper(src[++i]);
+ val[0] = ((val[0] >= 'A') && (val[0] <= 'F')) ? (val[0] - 'A' + 10) : (val[0] - '0');
+ val[1] = ((val[1] >= 'A') && (val[1] <= 'F')) ? (val[1] - 'A' + 10) : (val[1] - '0');
+ *(dst++) = val[0] * 16 + val[1];
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ val[0] = src[i] - '0';
+ val[1] = src[++i] - '0';
+ val[2] = src[++i] - '0';
+ *(dst++) = val[0] * 64 + val[1] * 8 + val[2];
+ break;
+
+ default:
+ *(dst++) = src[i];
+ break;
+ }
+ }
+ }
+
+ return (dst - s);
+}
+
+struct fstETab *fstUtilityExtractEnumTableFromString(const char *s)
+{
+ struct fstETab *et = NULL;
+ int num_spaces = 0;
+ int i;
+ int newlen;
+
+ if (s) {
+ const char *csp = strchr(s, ' ');
+ int cnt = atoi(csp + 1);
+
+ for (;;) {
+ csp = strchr(csp + 1, ' ');
+ if (csp) {
+ num_spaces++;
+ } else {
+ break;
+ }
+ }
+
+ if (num_spaces == (2 * cnt)) {
+ char *sp, *sp2;
+
+ et = (struct fstETab *)calloc(1, sizeof(struct fstETab));
+ et->elem_count = cnt;
+ et->name = strdup(s);
+ et->literal_arr = (char **)calloc(cnt, sizeof(char *));
+ et->val_arr = (char **)calloc(cnt, sizeof(char *));
+
+ sp = strchr(et->name, ' ');
+ *sp = 0;
+
+ sp = strchr(sp + 1, ' ');
+
+ for (i = 0; i < cnt; i++) {
+ sp2 = strchr(sp + 1, ' ');
+ *(char *)sp2 = 0;
+ et->literal_arr[i] = sp + 1;
+ sp = sp2;
+
+ newlen = fstUtilityEscToBin(NULL, (unsigned char *)et->literal_arr[i], strlen(et->literal_arr[i]));
+ et->literal_arr[i][newlen] = 0;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ sp2 = strchr(sp + 1, ' ');
+ if (sp2) {
+ *sp2 = 0;
+ }
+ et->val_arr[i] = sp + 1;
+ sp = sp2;
+
+ newlen = fstUtilityEscToBin(NULL, (unsigned char *)et->val_arr[i], strlen(et->val_arr[i]));
+ et->val_arr[i][newlen] = 0;
+ }
+ }
+ }
+
+ return (et);
+}
+
+void fstUtilityFreeEnumTable(struct fstETab *etab)
+{
+ if (etab) {
+ free(etab->literal_arr);
+ free(etab->val_arr);
+ free(etab->name);
+ free(etab);
+ }
+}
diff --git a/libs/fst/fstapi.h b/libs/fst/fstapi.h
new file mode 100644
index 000000000..a5e0971a1
--- /dev/null
+++ b/libs/fst/fstapi.h
@@ -0,0 +1,500 @@
+/*
+ * Copyright (c) 2009-2018 Tony Bybell.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#ifndef FST_API_H
+#define FST_API_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <inttypes.h>
+#if defined(_MSC_VER)
+#include "libs/zlib/zlib.h"
+#include <io.h>
+
+#include <process.h>
+
+#define ftruncate _chsize_s
+#define unlink _unlink
+#define fileno _fileno
+#define lseek _lseeki64
+
+#ifdef _WIN64
+#define ssize_t __int64
+#define SSIZE_MAX 9223372036854775807i64
+#else
+#define ssize_t long
+#define SSIZE_MAX 2147483647L
+#endif
+
+#include "stdint.h"
+#else
+#include <zlib.h>
+#include <unistd.h>
+#endif
+#include <time.h>
+
+#define FST_RDLOAD "FSTLOAD | "
+
+typedef uint32_t fstHandle;
+typedef uint32_t fstEnumHandle;
+
+enum fstWriterPackType
+{
+ FST_WR_PT_ZLIB = 0,
+ FST_WR_PT_FASTLZ = 1,
+ FST_WR_PT_LZ4 = 2
+};
+
+enum fstFileType
+{
+ FST_FT_MIN = 0,
+
+ FST_FT_VERILOG = 0,
+ FST_FT_VHDL = 1,
+ FST_FT_VERILOG_VHDL = 2,
+
+ FST_FT_MAX = 2
+};
+
+enum fstBlockType
+{
+ FST_BL_HDR = 0,
+ FST_BL_VCDATA = 1,
+ FST_BL_BLACKOUT = 2,
+ FST_BL_GEOM = 3,
+ FST_BL_HIER = 4,
+ FST_BL_VCDATA_DYN_ALIAS = 5,
+ FST_BL_HIER_LZ4 = 6,
+ FST_BL_HIER_LZ4DUO = 7,
+ FST_BL_VCDATA_DYN_ALIAS2 = 8,
+
+ FST_BL_ZWRAPPER = 254, /* indicates that whole trace is gz wrapped */
+ FST_BL_SKIP = 255 /* used while block is being written */
+};
+
+enum fstScopeType
+{
+ FST_ST_MIN = 0,
+
+ FST_ST_VCD_MODULE = 0,
+ FST_ST_VCD_TASK = 1,
+ FST_ST_VCD_FUNCTION = 2,
+ FST_ST_VCD_BEGIN = 3,
+ FST_ST_VCD_FORK = 4,
+ FST_ST_VCD_GENERATE = 5,
+ FST_ST_VCD_STRUCT = 6,
+ FST_ST_VCD_UNION = 7,
+ FST_ST_VCD_CLASS = 8,
+ FST_ST_VCD_INTERFACE = 9,
+ FST_ST_VCD_PACKAGE = 10,
+ FST_ST_VCD_PROGRAM = 11,
+
+ FST_ST_VHDL_ARCHITECTURE = 12,
+ FST_ST_VHDL_PROCEDURE = 13,
+ FST_ST_VHDL_FUNCTION = 14,
+ FST_ST_VHDL_RECORD = 15,
+ FST_ST_VHDL_PROCESS = 16,
+ FST_ST_VHDL_BLOCK = 17,
+ FST_ST_VHDL_FOR_GENERATE = 18,
+ FST_ST_VHDL_IF_GENERATE = 19,
+ FST_ST_VHDL_GENERATE = 20,
+ FST_ST_VHDL_PACKAGE = 21,
+
+ FST_ST_MAX = 21,
+
+ FST_ST_GEN_ATTRBEGIN = 252,
+ FST_ST_GEN_ATTREND = 253,
+
+ FST_ST_VCD_SCOPE = 254,
+ FST_ST_VCD_UPSCOPE = 255
+};
+
+enum fstVarType
+{
+ FST_VT_MIN = 0, /* start of vartypes */
+
+ FST_VT_VCD_EVENT = 0,
+ FST_VT_VCD_INTEGER = 1,
+ FST_VT_VCD_PARAMETER = 2,
+ FST_VT_VCD_REAL = 3,
+ FST_VT_VCD_REAL_PARAMETER = 4,
+ FST_VT_VCD_REG = 5,
+ FST_VT_VCD_SUPPLY0 = 6,
+ FST_VT_VCD_SUPPLY1 = 7,
+ FST_VT_VCD_TIME = 8,
+ FST_VT_VCD_TRI = 9,
+ FST_VT_VCD_TRIAND = 10,
+ FST_VT_VCD_TRIOR = 11,
+ FST_VT_VCD_TRIREG = 12,
+ FST_VT_VCD_TRI0 = 13,
+ FST_VT_VCD_TRI1 = 14,
+ FST_VT_VCD_WAND = 15,
+ FST_VT_VCD_WIRE = 16,
+ FST_VT_VCD_WOR = 17,
+ FST_VT_VCD_PORT = 18,
+ FST_VT_VCD_SPARRAY = 19, /* used to define the rownum (index) port for a sparse array */
+ FST_VT_VCD_REALTIME = 20,
+
+ FST_VT_GEN_STRING =
+ 21, /* generic string type (max len is defined dynamically via fstWriterEmitVariableLengthValueChange) */
+
+ FST_VT_SV_BIT = 22,
+ FST_VT_SV_LOGIC = 23,
+ FST_VT_SV_INT = 24, /* declare as size = 32 */
+ FST_VT_SV_SHORTINT = 25, /* declare as size = 16 */
+ FST_VT_SV_LONGINT = 26, /* declare as size = 64 */
+ FST_VT_SV_BYTE = 27, /* declare as size = 8 */
+ FST_VT_SV_ENUM = 28, /* declare as appropriate type range */
+ FST_VT_SV_SHORTREAL =
+ 29, /* declare and emit same as FST_VT_VCD_REAL (needs to be emitted as double, not a float) */
+
+ FST_VT_MAX = 29 /* end of vartypes */
+};
+
+enum fstVarDir
+{
+ FST_VD_MIN = 0,
+
+ FST_VD_IMPLICIT = 0,
+ FST_VD_INPUT = 1,
+ FST_VD_OUTPUT = 2,
+ FST_VD_INOUT = 3,
+ FST_VD_BUFFER = 4,
+ FST_VD_LINKAGE = 5,
+
+ FST_VD_MAX = 5
+};
+
+enum fstHierType
+{
+ FST_HT_MIN = 0,
+
+ FST_HT_SCOPE = 0,
+ FST_HT_UPSCOPE = 1,
+ FST_HT_VAR = 2,
+ FST_HT_ATTRBEGIN = 3,
+ FST_HT_ATTREND = 4,
+
+ /* FST_HT_TREEBEGIN and FST_HT_TREEEND are not yet used by FST but are currently used when fstHier bridges other
+ formats */
+ FST_HT_TREEBEGIN = 5,
+ FST_HT_TREEEND = 6,
+
+ FST_HT_MAX = 6
+};
+
+enum fstAttrType
+{
+ FST_AT_MIN = 0,
+
+ FST_AT_MISC = 0, /* self-contained: does not need matching FST_HT_ATTREND */
+ FST_AT_ARRAY = 1,
+ FST_AT_ENUM = 2,
+ FST_AT_PACK = 3,
+
+ FST_AT_MAX = 3
+};
+
+enum fstMiscType
+{
+ FST_MT_MIN = 0,
+
+ FST_MT_COMMENT = 0, /* use fstWriterSetComment() to emit */
+ FST_MT_ENVVAR = 1, /* use fstWriterSetEnvVar() to emit */
+ FST_MT_SUPVAR = 2, /* use fstWriterCreateVar2() to emit */
+ FST_MT_PATHNAME = 3, /* reserved for fstWriterSetSourceStem() string -> number management */
+ FST_MT_SOURCESTEM = 4, /* use fstWriterSetSourceStem() to emit */
+ FST_MT_SOURCEISTEM = 5, /* use fstWriterSetSourceInstantiationStem() to emit */
+ FST_MT_VALUELIST = 6, /* use fstWriterSetValueList() to emit, followed by fstWriterCreateVar*() */
+ FST_MT_ENUMTABLE = 7, /* use fstWriterCreateEnumTable() and fstWriterEmitEnumTableRef() to emit */
+ FST_MT_UNKNOWN = 8,
+
+ FST_MT_MAX = 8
+};
+
+enum fstArrayType
+{
+ FST_AR_MIN = 0,
+
+ FST_AR_NONE = 0,
+ FST_AR_UNPACKED = 1,
+ FST_AR_PACKED = 2,
+ FST_AR_SPARSE = 3,
+
+ FST_AR_MAX = 3
+};
+
+enum fstEnumValueType
+{
+ FST_EV_SV_INTEGER = 0,
+ FST_EV_SV_BIT = 1,
+ FST_EV_SV_LOGIC = 2,
+ FST_EV_SV_INT = 3,
+ FST_EV_SV_SHORTINT = 4,
+ FST_EV_SV_LONGINT = 5,
+ FST_EV_SV_BYTE = 6,
+ FST_EV_SV_UNSIGNED_INTEGER = 7,
+ FST_EV_SV_UNSIGNED_BIT = 8,
+ FST_EV_SV_UNSIGNED_LOGIC = 9,
+ FST_EV_SV_UNSIGNED_INT = 10,
+ FST_EV_SV_UNSIGNED_SHORTINT = 11,
+ FST_EV_SV_UNSIGNED_LONGINT = 12,
+ FST_EV_SV_UNSIGNED_BYTE = 13,
+
+ FST_EV_REG = 14,
+ FST_EV_TIME = 15,
+
+ FST_EV_MAX = 15
+};
+
+enum fstPackType
+{
+ FST_PT_NONE = 0,
+ FST_PT_UNPACKED = 1,
+ FST_PT_PACKED = 2,
+ FST_PT_TAGGED_PACKED = 3,
+
+ FST_PT_MAX = 3
+};
+
+enum fstSupplementalVarType
+{
+ FST_SVT_MIN = 0,
+
+ FST_SVT_NONE = 0,
+
+ FST_SVT_VHDL_SIGNAL = 1,
+ FST_SVT_VHDL_VARIABLE = 2,
+ FST_SVT_VHDL_CONSTANT = 3,
+ FST_SVT_VHDL_FILE = 4,
+ FST_SVT_VHDL_MEMORY = 5,
+
+ FST_SVT_MAX = 5
+};
+
+enum fstSupplementalDataType
+{
+ FST_SDT_MIN = 0,
+
+ FST_SDT_NONE = 0,
+
+ FST_SDT_VHDL_BOOLEAN = 1,
+ FST_SDT_VHDL_BIT = 2,
+ FST_SDT_VHDL_BIT_VECTOR = 3,
+ FST_SDT_VHDL_STD_ULOGIC = 4,
+ FST_SDT_VHDL_STD_ULOGIC_VECTOR = 5,
+ FST_SDT_VHDL_STD_LOGIC = 6,
+ FST_SDT_VHDL_STD_LOGIC_VECTOR = 7,
+ FST_SDT_VHDL_UNSIGNED = 8,
+ FST_SDT_VHDL_SIGNED = 9,
+ FST_SDT_VHDL_INTEGER = 10,
+ FST_SDT_VHDL_REAL = 11,
+ FST_SDT_VHDL_NATURAL = 12,
+ FST_SDT_VHDL_POSITIVE = 13,
+ FST_SDT_VHDL_TIME = 14,
+ FST_SDT_VHDL_CHARACTER = 15,
+ FST_SDT_VHDL_STRING = 16,
+
+ FST_SDT_MAX = 16,
+
+ FST_SDT_SVT_SHIFT_COUNT =
+ 10, /* FST_SVT_* is ORed in by fstWriterCreateVar2() to the left after shifting FST_SDT_SVT_SHIFT_COUNT */
+ FST_SDT_ABS_MAX = ((1 << (FST_SDT_SVT_SHIFT_COUNT)) - 1)
+};
+
+struct fstHier
+{
+ unsigned char htyp;
+
+ union
+ {
+ /* if htyp == FST_HT_SCOPE */
+ struct fstHierScope
+ {
+ unsigned char typ; /* FST_ST_MIN ... FST_ST_MAX */
+ const char *name;
+ const char *component;
+ uint32_t name_length; /* strlen(u.scope.name) */
+ uint32_t component_length; /* strlen(u.scope.component) */
+ } scope;
+
+ /* if htyp == FST_HT_VAR */
+ struct fstHierVar
+ {
+ unsigned char typ; /* FST_VT_MIN ... FST_VT_MAX */
+ unsigned char direction; /* FST_VD_MIN ... FST_VD_MAX */
+ unsigned char svt_workspace; /* zeroed out by FST reader, for client code use */
+ unsigned char sdt_workspace; /* zeroed out by FST reader, for client code use */
+ unsigned int sxt_workspace; /* zeroed out by FST reader, for client code use */
+ const char *name;
+ uint32_t length;
+ fstHandle handle;
+ uint32_t name_length; /* strlen(u.var.name) */
+ unsigned is_alias : 1;
+ } var;
+
+ /* if htyp == FST_HT_ATTRBEGIN */
+ struct fstHierAttr
+ {
+ unsigned char typ; /* FST_AT_MIN ... FST_AT_MAX */
+ unsigned char subtype; /* from fstMiscType, fstArrayType, fstEnumValueType, fstPackType */
+ const char *name;
+ uint64_t arg; /* number of array elements, struct members, or some other payload (possibly ignored) */
+ uint64_t arg_from_name; /* for when name is overloaded as a variable-length integer (FST_AT_MISC +
+ FST_MT_SOURCESTEM) */
+ uint32_t name_length; /* strlen(u.attr.name) */
+ } attr;
+ } u;
+};
+
+struct fstETab
+{
+ char *name;
+ uint32_t elem_count;
+ char **literal_arr;
+ char **val_arr;
+};
+
+/*
+ * writer functions
+ */
+void fstWriterClose(void *ctx);
+void *fstWriterCreate(const char *nam, int use_compressed_hier);
+fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t elem_count, unsigned int min_valbits,
+ const char **literal_arr, const char **val_arr);
+/* used for Verilog/SV */
+fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd, uint32_t len, const char *nam,
+ fstHandle aliasHandle);
+/* future expansion for VHDL and other languages. The variable type, data type, etc map onto
+ the current Verilog/SV one. The "type" string is optional for a more verbose or custom description */
+fstHandle fstWriterCreateVar2(void *ctx, enum fstVarType vt, enum fstVarDir vd, uint32_t len, const char *nam,
+ fstHandle aliasHandle, const char *type, enum fstSupplementalVarType svt,
+ enum fstSupplementalDataType sdt);
+void fstWriterEmitDumpActive(void *ctx, int enable);
+void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle);
+void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val);
+void fstWriterEmitValueChange32(void *ctx, fstHandle handle, uint32_t bits, uint32_t val);
+void fstWriterEmitValueChange64(void *ctx, fstHandle handle, uint32_t bits, uint64_t val);
+void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle, uint32_t bits, const uint32_t *val);
+void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle, uint32_t bits, const uint64_t *val);
+void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const void *val, uint32_t len);
+void fstWriterEmitTimeChange(void *ctx, uint64_t tim);
+void fstWriterFlushContext(void *ctx);
+int fstWriterGetDumpSizeLimitReached(void *ctx);
+int fstWriterGetFseekFailed(void *ctx);
+void fstWriterSetAttrBegin(void *ctx, enum fstAttrType attrtype, int subtype, const char *attrname, uint64_t arg);
+void fstWriterSetAttrEnd(void *ctx);
+void fstWriterSetComment(void *ctx, const char *comm);
+void fstWriterSetDate(void *ctx, const char *dat);
+void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes);
+void fstWriterSetEnvVar(void *ctx, const char *envvar);
+void fstWriterSetFileType(void *ctx, enum fstFileType filetype);
+void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ);
+void fstWriterSetParallelMode(void *ctx, int enable);
+void fstWriterSetRepackOnClose(void *ctx, int enable); /* type = 0 (none), 1 (libz) */
+void fstWriterSetScope(void *ctx, enum fstScopeType scopetype, const char *scopename, const char *scopecomp);
+void fstWriterSetSourceInstantiationStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath);
+void fstWriterSetSourceStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath);
+void fstWriterSetTimescale(void *ctx, int ts);
+void fstWriterSetTimescaleFromString(void *ctx, const char *s);
+void fstWriterSetTimezero(void *ctx, int64_t tim);
+void fstWriterSetUpscope(void *ctx);
+void fstWriterSetValueList(void *ctx, const char *vl);
+void fstWriterSetVersion(void *ctx, const char *vers);
+
+/*
+ * reader functions
+ */
+void fstReaderClose(void *ctx);
+void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx);
+void fstReaderClrFacProcessMaskAll(void *ctx);
+uint64_t fstReaderGetAliasCount(void *ctx);
+const char *fstReaderGetCurrentFlatScope(void *ctx);
+void *fstReaderGetCurrentScopeUserInfo(void *ctx);
+int fstReaderGetCurrentScopeLen(void *ctx);
+const char *fstReaderGetDateString(void *ctx);
+int fstReaderGetDoubleEndianMatchState(void *ctx);
+uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx);
+unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx);
+uint64_t fstReaderGetEndTime(void *ctx);
+int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx);
+int fstReaderGetFileType(void *ctx);
+int fstReaderGetFseekFailed(void *ctx);
+fstHandle fstReaderGetMaxHandle(void *ctx);
+uint64_t fstReaderGetMemoryUsedByWriter(void *ctx);
+uint32_t fstReaderGetNumberDumpActivityChanges(void *ctx);
+uint64_t fstReaderGetScopeCount(void *ctx);
+uint64_t fstReaderGetStartTime(void *ctx);
+signed char fstReaderGetTimescale(void *ctx);
+int64_t fstReaderGetTimezero(void *ctx);
+uint64_t fstReaderGetValueChangeSectionCount(void *ctx);
+char *fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf);
+uint64_t fstReaderGetVarCount(void *ctx);
+const char *fstReaderGetVersionString(void *ctx);
+struct fstHier *fstReaderIterateHier(void *ctx);
+int fstReaderIterateHierRewind(void *ctx);
+int fstReaderIterBlocks(void *ctx,
+ void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx,
+ const unsigned char *value),
+ void *user_callback_data_pointer, FILE *vcdhandle);
+int fstReaderIterBlocks2(void *ctx,
+ void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time,
+ fstHandle facidx, const unsigned char *value),
+ void (*value_change_callback_varlen)(void *user_callback_data_pointer, uint64_t time,
+ fstHandle facidx, const unsigned char *value,
+ uint32_t len),
+ void *user_callback_data_pointer, FILE *vcdhandle);
+void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable);
+void *fstReaderOpen(const char *nam);
+void *fstReaderOpenForUtilitiesOnly(void);
+const char *fstReaderPopScope(void *ctx);
+int fstReaderProcessHier(void *ctx, FILE *vcdhandle);
+const char *fstReaderPushScope(void *ctx, const char *nam, void *user_info);
+void fstReaderResetScope(void *ctx);
+void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx);
+void fstReaderSetFacProcessMaskAll(void *ctx);
+void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time);
+void fstReaderSetUnlimitedTimeRange(void *ctx);
+void fstReaderSetVcdExtensions(void *ctx, int enable);
+
+/*
+ * utility functions
+ */
+int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len); /* used for mallocs for fstUtilityBinToEsc() */
+int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len);
+int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len);
+struct fstETab *fstUtilityExtractEnumTableFromString(const char *s);
+void fstUtilityFreeEnumTable(struct fstETab *etab); /* must use to free fstETab properly */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/fst/lz4.cc b/libs/fst/lz4.cc
new file mode 100644
index 000000000..7e94f2492
--- /dev/null
+++ b/libs/fst/lz4.cc
@@ -0,0 +1,1615 @@
+/*
+ LZ4 - Fast LZ compression algorithm
+ Copyright (C) 2011-2015, Yann Collet.
+
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ SPDX-License-Identifier: BSD-2-Clause
+
+ You can contact the author at :
+ - LZ4 source repository : https://github.com/Cyan4973/lz4
+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
+*/
+
+/**************************************
+ * Tuning parameters
+ **************************************/
+/*
+ * HEAPMODE :
+ * Select how default compression functions will allocate memory for their hash table,
+ * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
+ */
+#define HEAPMODE 0
+
+/*
+ * ACCELERATION_DEFAULT :
+ * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0
+ */
+#define ACCELERATION_DEFAULT 1
+
+/**************************************
+ * CPU Feature Detection
+ **************************************/
+/*
+ * LZ4_FORCE_SW_BITCOUNT
+ * Define this parameter if your target system or compiler does not support hardware bit count
+ */
+#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for Windows CE does not support Hardware bit count */
+#define LZ4_FORCE_SW_BITCOUNT
+#endif
+
+/**************************************
+ * Includes
+ **************************************/
+#include "lz4.h"
+
+/**************************************
+ * Compiler Options
+ **************************************/
+#ifdef _MSC_VER /* Visual Studio */
+#define FORCE_INLINE static __forceinline
+#include <intrin.h>
+#pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
+#pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */
+#else
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
+#if defined(__GNUC__) || defined(__clang__)
+#define FORCE_INLINE static inline __attribute__((always_inline))
+#else
+#define FORCE_INLINE static inline
+#endif
+#else
+#define FORCE_INLINE static
+#endif /* __STDC_VERSION__ */
+#endif /* _MSC_VER */
+
+/* LZ4_GCC_VERSION is defined into lz4.h */
+#if (LZ4_GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
+#define expect(expr, value) (__builtin_expect((expr), (value)))
+#else
+#define expect(expr, value) (expr)
+#endif
+
+#define likely(expr) expect((expr) != 0, 1)
+#define unlikely(expr) expect((expr) != 0, 0)
+
+/**************************************
+ * Memory routines
+ **************************************/
+#include <stdlib.h> /* malloc, calloc, free */
+#define ALLOCATOR(n, s) calloc(n, s)
+#define FREEMEM free
+#include <string.h> /* memset, memcpy */
+#define MEM_INIT memset
+
+/**************************************
+ * Basic Types
+ **************************************/
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
+#include <stdint.h>
+typedef uint8_t BYTE;
+typedef uint16_t U16;
+typedef uint32_t U32;
+typedef int32_t S32;
+typedef uint64_t U64;
+#else
+typedef unsigned char BYTE;
+typedef unsigned short U16;
+typedef unsigned int U32;
+typedef signed int S32;
+typedef unsigned long long U64;
+#endif
+
+/**************************************
+ * Reading and writing into memory
+ **************************************/
+#define STEPSIZE sizeof(size_t)
+
+static unsigned LZ4_64bits(void) { return sizeof(void *) == 8; }
+
+static unsigned LZ4_isLittleEndian(void)
+{
+ const union
+ {
+ U32 i;
+ BYTE c[4];
+ } one = {1}; /* don't use static : performance detrimental */
+ return one.c[0];
+}
+
+static U16 LZ4_read16(const void *memPtr)
+{
+ U16 val16;
+ memcpy(&val16, memPtr, 2);
+ return val16;
+}
+
+static U16 LZ4_readLE16(const void *memPtr)
+{
+ if (LZ4_isLittleEndian()) {
+ return LZ4_read16(memPtr);
+ } else {
+ const BYTE *p = (const BYTE *)memPtr;
+ return (U16)((U16)p[0] + (p[1] << 8));
+ }
+}
+
+static void LZ4_writeLE16(void *memPtr, U16 value)
+{
+ if (LZ4_isLittleEndian()) {
+ memcpy(memPtr, &value, 2);
+ } else {
+ BYTE *p = (BYTE *)memPtr;
+ p[0] = (BYTE)value;
+ p[1] = (BYTE)(value >> 8);
+ }
+}
+
+static U32 LZ4_read32(const void *memPtr)
+{
+ U32 val32;
+ memcpy(&val32, memPtr, 4);
+ return val32;
+}
+
+static U64 LZ4_read64(const void *memPtr)
+{
+ U64 val64;
+ memcpy(&val64, memPtr, 8);
+ return val64;
+}
+
+static size_t LZ4_read_ARCH(const void *p)
+{
+ if (LZ4_64bits())
+ return (size_t)LZ4_read64(p);
+ else
+ return (size_t)LZ4_read32(p);
+}
+
+static void LZ4_copy4(void *dstPtr, const void *srcPtr) { memcpy(dstPtr, srcPtr, 4); }
+
+static void LZ4_copy8(void *dstPtr, const void *srcPtr) { memcpy(dstPtr, srcPtr, 8); }
+
+/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */
+static void LZ4_wildCopy(void *dstPtr, const void *srcPtr, void *dstEnd)
+{
+ BYTE *d = (BYTE *)dstPtr;
+ const BYTE *s = (const BYTE *)srcPtr;
+ BYTE *e = (BYTE *)dstEnd;
+ do {
+ LZ4_copy8(d, s);
+ d += 8;
+ s += 8;
+ } while (d < e);
+}
+
+/**************************************
+ * Common Constants
+ **************************************/
+#define MINMATCH 4
+
+#define COPYLENGTH 8
+#define LASTLITERALS 5
+#define MFLIMIT (COPYLENGTH + MINMATCH)
+static const int LZ4_minLength = (MFLIMIT + 1);
+
+#define KB *(1 << 10)
+#define MB *(1 << 20)
+#define GB *(1U << 30)
+
+#define MAXD_LOG 16
+#ifdef MAX_DISTANCE
+#undef MAX_DISTANCE
+#endif
+#define MAX_DISTANCE ((1 << MAXD_LOG) - 1)
+
+#define ML_BITS 4
+#define ML_MASK ((1U << ML_BITS) - 1)
+#define RUN_BITS (8 - ML_BITS)
+#define RUN_MASK ((1U << RUN_BITS) - 1)
+
+/**************************************
+ * Common Utils
+ **************************************/
+#define LZ4_STATIC_ASSERT(c) \
+ { \
+ enum \
+ { \
+ LZ4_static_assert = 1 / (int)(!!(c)) \
+ }; \
+ } /* use only *after* variable declarations */
+
+/**************************************
+ * Common functions
+ **************************************/
+static unsigned LZ4_NbCommonBytes(size_t val)
+{
+ if (LZ4_isLittleEndian()) {
+ if (LZ4_64bits()) {
+#if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ unsigned long r = 0;
+ _BitScanForward64(&r, (U64)val);
+ return (int)(r >> 3);
+#elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ return (__builtin_ctzll((U64)val) >> 3);
+#else
+ static const int DeBruijnBytePos[64] = {0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5,
+ 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5,
+ 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7};
+ return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
+#endif
+ } else /* 32 bits */
+ {
+#if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ unsigned long r;
+ _BitScanForward(&r, (U32)val);
+ return (int)(r >> 3);
+#elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ return (__builtin_ctz((U32)val) >> 3);
+#else
+ static const int DeBruijnBytePos[32] = {0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1,
+ 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1};
+ return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
+#endif
+ }
+ } else /* Big Endian CPU */
+ {
+ if (LZ4_64bits()) {
+#if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ unsigned long r = 0;
+ _BitScanReverse64(&r, val);
+ return (unsigned)(r >> 3);
+#elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ return (__builtin_clzll((U64)val) >> 3);
+#else
+ unsigned r;
+ if (!(val >> 32)) {
+ r = 4;
+ } else {
+ r = 0;
+ val >>= 32;
+ }
+ if (!(val >> 16)) {
+ r += 2;
+ val >>= 8;
+ } else {
+ val >>= 24;
+ }
+ r += (!val);
+ return r;
+#endif
+ } else /* 32 bits */
+ {
+#if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ unsigned long r = 0;
+ _BitScanReverse(&r, (unsigned long)val);
+ return (unsigned)(r >> 3);
+#elif (defined(__clang__) || (LZ4_GCC_VERSION >= 304)) && !defined(LZ4_FORCE_SW_BITCOUNT)
+ return (__builtin_clz((U32)val) >> 3);
+#else
+ unsigned r;
+ if (!(val >> 16)) {
+ r = 2;
+ val >>= 8;
+ } else {
+ r = 0;
+ val >>= 24;
+ }
+ r += (!val);
+ return r;
+#endif
+ }
+ }
+}
+
+static unsigned LZ4_count(const BYTE *pIn, const BYTE *pMatch, const BYTE *pInLimit)
+{
+ const BYTE *const pStart = pIn;
+
+ while (likely(pIn < pInLimit - (STEPSIZE - 1))) {
+ size_t diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
+ if (!diff) {
+ pIn += STEPSIZE;
+ pMatch += STEPSIZE;
+ continue;
+ }
+ pIn += LZ4_NbCommonBytes(diff);
+ return (unsigned)(pIn - pStart);
+ }
+
+ if (LZ4_64bits())
+ if ((pIn < (pInLimit - 3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) {
+ pIn += 4;
+ pMatch += 4;
+ }
+ if ((pIn < (pInLimit - 1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) {
+ pIn += 2;
+ pMatch += 2;
+ }
+ if ((pIn < pInLimit) && (*pMatch == *pIn))
+ pIn++;
+ return (unsigned)(pIn - pStart);
+}
+
+#ifndef LZ4_COMMONDEFS_ONLY
+/**************************************
+ * Local Constants
+ **************************************/
+#define LZ4_HASHLOG (LZ4_MEMORY_USAGE - 2)
+#define HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
+#define HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
+
+static const int LZ4_64Klimit = ((64 KB) + (MFLIMIT - 1));
+static const U32 LZ4_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */
+
+/**************************************
+ * Local Structures and types
+ **************************************/
+typedef struct
+{
+ U32 hashTable[HASH_SIZE_U32];
+ U32 currentOffset;
+ U32 initCheck;
+ const BYTE *dictionary;
+ BYTE *bufferStart; /* obsolete, used for slideInputBuffer */
+ U32 dictSize;
+} LZ4_stream_t_internal;
+
+typedef enum
+{
+ notLimited = 0,
+ limitedOutput = 1
+} limitedOutput_directive;
+typedef enum
+{
+ byPtr,
+ byU32,
+ byU16
+} tableType_t;
+
+typedef enum
+{
+ noDict = 0,
+ withPrefix64k,
+ usingExtDict
+} dict_directive;
+typedef enum
+{
+ noDictIssue = 0,
+ dictSmall
+} dictIssue_directive;
+
+typedef enum
+{
+ endOnOutputSize = 0,
+ endOnInputSize = 1
+} endCondition_directive;
+typedef enum
+{
+ full = 0,
+ partial = 1
+} earlyEnd_directive;
+
+/**************************************
+ * Local Utils
+ **************************************/
+int LZ4_versionNumber(void) { return LZ4_VERSION_NUMBER; }
+int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); }
+int LZ4_sizeofState() { return LZ4_STREAMSIZE; }
+
+/********************************
+ * Compression functions
+ ********************************/
+
+static U32 LZ4_hashSequence(U32 sequence, tableType_t const tableType)
+{
+ if (tableType == byU16)
+ return (((sequence)*2654435761U) >> ((MINMATCH * 8) - (LZ4_HASHLOG + 1)));
+ else
+ return (((sequence)*2654435761U) >> ((MINMATCH * 8) - LZ4_HASHLOG));
+}
+
+static const U64 prime5bytes = 889523592379ULL;
+static U32 LZ4_hashSequence64(size_t sequence, tableType_t const tableType)
+{
+ const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG + 1 : LZ4_HASHLOG;
+ const U32 hashMask = (1 << hashLog) - 1;
+ return ((sequence * prime5bytes) >> (40 - hashLog)) & hashMask;
+}
+
+static U32 LZ4_hashSequenceT(size_t sequence, tableType_t const tableType)
+{
+ if (LZ4_64bits())
+ return LZ4_hashSequence64(sequence, tableType);
+ return LZ4_hashSequence((U32)sequence, tableType);
+}
+
+static U32 LZ4_hashPosition(const void *p, tableType_t tableType)
+{
+ return LZ4_hashSequenceT(LZ4_read_ARCH(p), tableType);
+}
+
+static void LZ4_putPositionOnHash(const BYTE *p, U32 h, void *tableBase, tableType_t const tableType,
+ const BYTE *srcBase)
+{
+ switch (tableType) {
+ case byPtr: {
+ const BYTE **hashTable = (const BYTE **)tableBase;
+ hashTable[h] = p;
+ return;
+ }
+ case byU32: {
+ U32 *hashTable = (U32 *)tableBase;
+ hashTable[h] = (U32)(p - srcBase);
+ return;
+ }
+ case byU16: {
+ U16 *hashTable = (U16 *)tableBase;
+ hashTable[h] = (U16)(p - srcBase);
+ return;
+ }
+ }
+}
+
+static void LZ4_putPosition(const BYTE *p, void *tableBase, tableType_t tableType, const BYTE *srcBase)
+{
+ U32 h = LZ4_hashPosition(p, tableType);
+ LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase);
+}
+
+static const BYTE *LZ4_getPositionOnHash(U32 h, void *tableBase, tableType_t tableType, const BYTE *srcBase)
+{
+ if (tableType == byPtr) {
+ const BYTE **hashTable = (const BYTE **)tableBase;
+ return hashTable[h];
+ }
+ if (tableType == byU32) {
+ U32 *hashTable = (U32 *)tableBase;
+ return hashTable[h] + srcBase;
+ }
+ {
+ U16 *hashTable = (U16 *)tableBase;
+ return hashTable[h] + srcBase;
+ } /* default, to ensure a return */
+}
+
+static const BYTE *LZ4_getPosition(const BYTE *p, void *tableBase, tableType_t tableType, const BYTE *srcBase)
+{
+ U32 h = LZ4_hashPosition(p, tableType);
+ return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
+}
+
+FORCE_INLINE int LZ4_compress_generic(void *const ctx, const char *const source, char *const dest, const int inputSize,
+ const int maxOutputSize, const limitedOutput_directive outputLimited,
+ const tableType_t tableType, const dict_directive dict,
+ const dictIssue_directive dictIssue, const U32 acceleration)
+{
+ LZ4_stream_t_internal *const dictPtr = (LZ4_stream_t_internal *)ctx;
+
+ const BYTE *ip = (const BYTE *)source;
+ const BYTE *base;
+ const BYTE *lowLimit;
+ const BYTE *const lowRefLimit = ip - dictPtr->dictSize;
+ const BYTE *const dictionary = dictPtr->dictionary;
+ const BYTE *const dictEnd = dictionary + dictPtr->dictSize;
+ const size_t dictDelta = dictEnd - (const BYTE *)source;
+ const BYTE *anchor = (const BYTE *)source;
+ const BYTE *const iend = ip + inputSize;
+ const BYTE *const mflimit = iend - MFLIMIT;
+ const BYTE *const matchlimit = iend - LASTLITERALS;
+
+ BYTE *op = (BYTE *)dest;
+ BYTE *const olimit = op + maxOutputSize;
+
+ U32 forwardH;
+ size_t refDelta = 0;
+
+ /* Init conditions */
+ if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE)
+ return 0; /* Unsupported input size, too large (or negative) */
+ switch (dict) {
+ case noDict:
+ default:
+ base = (const BYTE *)source;
+ lowLimit = (const BYTE *)source;
+ break;
+ case withPrefix64k:
+ base = (const BYTE *)source - dictPtr->currentOffset;
+ lowLimit = (const BYTE *)source - dictPtr->dictSize;
+ break;
+ case usingExtDict:
+ base = (const BYTE *)source - dictPtr->currentOffset;
+ lowLimit = (const BYTE *)source;
+ break;
+ }
+ if ((tableType == byU16) && (inputSize >= LZ4_64Klimit))
+ return 0; /* Size too large (not within 64K limit) */
+ if (inputSize < LZ4_minLength)
+ goto _last_literals; /* Input too small, no compression (all literals) */
+
+ /* First Byte */
+ LZ4_putPosition(ip, ctx, tableType, base);
+ ip++;
+ forwardH = LZ4_hashPosition(ip, tableType);
+
+ /* Main Loop */
+ for (;;) {
+ const BYTE *match;
+ BYTE *token;
+ {
+ const BYTE *forwardIp = ip;
+ unsigned step = 1;
+ unsigned searchMatchNb = acceleration << LZ4_skipTrigger;
+
+ /* Find a match */
+ do {
+ U32 h = forwardH;
+ ip = forwardIp;
+ forwardIp += step;
+ step = (searchMatchNb++ >> LZ4_skipTrigger);
+
+ if (unlikely(forwardIp > mflimit))
+ goto _last_literals;
+
+ match = LZ4_getPositionOnHash(h, ctx, tableType, base);
+ if (dict == usingExtDict) {
+ if (match < (const BYTE *)source) {
+ refDelta = dictDelta;
+ lowLimit = dictionary;
+ } else {
+ refDelta = 0;
+ lowLimit = (const BYTE *)source;
+ }
+ }
+ forwardH = LZ4_hashPosition(forwardIp, tableType);
+ LZ4_putPositionOnHash(ip, h, ctx, tableType, base);
+
+ } while (((dictIssue == dictSmall) ? (match < lowRefLimit) : 0) ||
+ ((tableType == byU16) ? 0 : (match + MAX_DISTANCE < ip)) ||
+ (LZ4_read32(match + refDelta) != LZ4_read32(ip)));
+ }
+
+ /* Catch up */
+ while ((ip > anchor) && (match + refDelta > lowLimit) && (unlikely(ip[-1] == match[refDelta - 1]))) {
+ ip--;
+ match--;
+ }
+
+ {
+ /* Encode Literal length */
+ unsigned litLength = (unsigned)(ip - anchor);
+ token = op++;
+ if ((outputLimited) && (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength / 255) > olimit)))
+ return 0; /* Check output limit */
+ if (litLength >= RUN_MASK) {
+ int len = (int)litLength - RUN_MASK;
+ *token = (RUN_MASK << ML_BITS);
+ for (; len >= 255; len -= 255)
+ *op++ = 255;
+ *op++ = (BYTE)len;
+ } else
+ *token = (BYTE)(litLength << ML_BITS);
+
+ /* Copy Literals */
+ LZ4_wildCopy(op, anchor, op + litLength);
+ op += litLength;
+ }
+
+ _next_match:
+ /* Encode Offset */
+ LZ4_writeLE16(op, (U16)(ip - match));
+ op += 2;
+
+ /* Encode MatchLength */
+ {
+ unsigned matchLength;
+
+ if ((dict == usingExtDict) && (lowLimit == dictionary)) {
+ const BYTE *limit;
+ match += refDelta;
+ limit = ip + (dictEnd - match);
+ if (limit > matchlimit)
+ limit = matchlimit;
+ matchLength = LZ4_count(ip + MINMATCH, match + MINMATCH, limit);
+ ip += MINMATCH + matchLength;
+ if (ip == limit) {
+ unsigned more = LZ4_count(ip, (const BYTE *)source, matchlimit);
+ matchLength += more;
+ ip += more;
+ }
+ } else {
+ matchLength = LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit);
+ ip += MINMATCH + matchLength;
+ }
+
+ if ((outputLimited) && (unlikely(op + (1 + LASTLITERALS) + (matchLength >> 8) > olimit)))
+ return 0; /* Check output limit */
+ if (matchLength >= ML_MASK) {
+ *token += ML_MASK;
+ matchLength -= ML_MASK;
+ for (; matchLength >= 510; matchLength -= 510) {
+ *op++ = 255;
+ *op++ = 255;
+ }
+ if (matchLength >= 255) {
+ matchLength -= 255;
+ *op++ = 255;
+ }
+ *op++ = (BYTE)matchLength;
+ } else
+ *token += (BYTE)(matchLength);
+ }
+
+ anchor = ip;
+
+ /* Test end of chunk */
+ if (ip > mflimit)
+ break;
+
+ /* Fill table */
+ LZ4_putPosition(ip - 2, ctx, tableType, base);
+
+ /* Test next position */
+ match = LZ4_getPosition(ip, ctx, tableType, base);
+ if (dict == usingExtDict) {
+ if (match < (const BYTE *)source) {
+ refDelta = dictDelta;
+ lowLimit = dictionary;
+ } else {
+ refDelta = 0;
+ lowLimit = (const BYTE *)source;
+ }
+ }
+ LZ4_putPosition(ip, ctx, tableType, base);
+ if (((dictIssue == dictSmall) ? (match >= lowRefLimit) : 1) && (match + MAX_DISTANCE >= ip) &&
+ (LZ4_read32(match + refDelta) == LZ4_read32(ip))) {
+ token = op++;
+ *token = 0;
+ goto _next_match;
+ }
+
+ /* Prepare next loop */
+ forwardH = LZ4_hashPosition(++ip, tableType);
+ }
+
+_last_literals:
+ /* Encode Last Literals */
+ {
+ const size_t lastRun = (size_t)(iend - anchor);
+ if ((outputLimited) &&
+ ((op - (BYTE *)dest) + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > (U32)maxOutputSize))
+ return 0; /* Check output limit */
+ if (lastRun >= RUN_MASK) {
+ size_t accumulator = lastRun - RUN_MASK;
+ *op++ = RUN_MASK << ML_BITS;
+ for (; accumulator >= 255; accumulator -= 255)
+ *op++ = 255;
+ *op++ = (BYTE)accumulator;
+ } else {
+ *op++ = (BYTE)(lastRun << ML_BITS);
+ }
+ memcpy(op, anchor, lastRun);
+ op += lastRun;
+ }
+
+ /* End */
+ return (int)(((char *)op) - dest);
+}
+
+int LZ4_compress_fast_extState(void *state, const char *source, char *dest, int inputSize, int maxOutputSize,
+ int acceleration)
+{
+ LZ4_resetStream((LZ4_stream_t *)state);
+ if (acceleration < 1)
+ acceleration = ACCELERATION_DEFAULT;
+
+ if (maxOutputSize >= LZ4_compressBound(inputSize)) {
+ if (inputSize < LZ4_64Klimit)
+ return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue,
+ acceleration);
+ else
+ return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, LZ4_64bits() ? byU32 : byPtr,
+ noDict, noDictIssue, acceleration);
+ } else {
+ if (inputSize < LZ4_64Klimit)
+ return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict,
+ noDictIssue, acceleration);
+ else
+ return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput,
+ LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
+ }
+}
+
+int LZ4_compress_fast(const char *source, char *dest, int inputSize, int maxOutputSize, int acceleration)
+{
+#if (HEAPMODE)
+ void *ctxPtr = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */
+#else
+ LZ4_stream_t ctx;
+ void *ctxPtr = &ctx;
+#endif
+
+ int result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);
+
+#if (HEAPMODE)
+ FREEMEM(ctxPtr);
+#endif
+ return result;
+}
+
+int LZ4_compress_default(const char *source, char *dest, int inputSize, int maxOutputSize)
+{
+ return LZ4_compress_fast(source, dest, inputSize, maxOutputSize, 1);
+}
+
+/* hidden debug function */
+/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */
+int LZ4_compress_fast_force(const char *source, char *dest, int inputSize, int maxOutputSize, int acceleration)
+{
+ LZ4_stream_t ctx;
+
+ LZ4_resetStream(&ctx);
+
+ if (inputSize < LZ4_64Klimit)
+ return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict,
+ noDictIssue, acceleration);
+ else
+ return LZ4_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput,
+ LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);
+}
+
+/********************************
+ * destSize variant
+ ********************************/
+
+static int LZ4_compress_destSize_generic(void *const ctx, const char *const src, char *const dst, int *const srcSizePtr,
+ const int targetDstSize, const tableType_t tableType)
+{
+ const BYTE *ip = (const BYTE *)src;
+ const BYTE *base = (const BYTE *)src;
+ const BYTE *lowLimit = (const BYTE *)src;
+ const BYTE *anchor = ip;
+ const BYTE *const iend = ip + *srcSizePtr;
+ const BYTE *const mflimit = iend - MFLIMIT;
+ const BYTE *const matchlimit = iend - LASTLITERALS;
+
+ BYTE *op = (BYTE *)dst;
+ BYTE *const oend = op + targetDstSize;
+ BYTE *const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */;
+ BYTE *const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */);
+ BYTE *const oMaxSeq = oMaxLit - 1 /* token */;
+
+ U32 forwardH;
+
+ /* Init conditions */
+ if (targetDstSize < 1)
+ return 0; /* Impossible to store anything */
+ if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE)
+ return 0; /* Unsupported input size, too large (or negative) */
+ if ((tableType == byU16) && (*srcSizePtr >= LZ4_64Klimit))
+ return 0; /* Size too large (not within 64K limit) */
+ if (*srcSizePtr < LZ4_minLength)
+ goto _last_literals; /* Input too small, no compression (all literals) */
+
+ /* First Byte */
+ *srcSizePtr = 0;
+ LZ4_putPosition(ip, ctx, tableType, base);
+ ip++;
+ forwardH = LZ4_hashPosition(ip, tableType);
+
+ /* Main Loop */
+ for (;;) {
+ const BYTE *match;
+ BYTE *token;
+ {
+ const BYTE *forwardIp = ip;
+ unsigned step = 1;
+ unsigned searchMatchNb = 1 << LZ4_skipTrigger;
+
+ /* Find a match */
+ do {
+ U32 h = forwardH;
+ ip = forwardIp;
+ forwardIp += step;
+ step = (searchMatchNb++ >> LZ4_skipTrigger);
+
+ if (unlikely(forwardIp > mflimit))
+ goto _last_literals;
+
+ match = LZ4_getPositionOnHash(h, ctx, tableType, base);
+ forwardH = LZ4_hashPosition(forwardIp, tableType);
+ LZ4_putPositionOnHash(ip, h, ctx, tableType, base);
+
+ } while (((tableType == byU16) ? 0 : (match + MAX_DISTANCE < ip)) || (LZ4_read32(match) != LZ4_read32(ip)));
+ }
+
+ /* Catch up */
+ while ((ip > anchor) && (match > lowLimit) && (unlikely(ip[-1] == match[-1]))) {
+ ip--;
+ match--;
+ }
+
+ {
+ /* Encode Literal length */
+ unsigned litLength = (unsigned)(ip - anchor);
+ token = op++;
+ if (op + ((litLength + 240) / 255) + litLength > oMaxLit) {
+ /* Not enough space for a last match */
+ op--;
+ goto _last_literals;
+ }
+ if (litLength >= RUN_MASK) {
+ unsigned len = litLength - RUN_MASK;
+ *token = (RUN_MASK << ML_BITS);
+ for (; len >= 255; len -= 255)
+ *op++ = 255;
+ *op++ = (BYTE)len;
+ } else
+ *token = (BYTE)(litLength << ML_BITS);
+
+ /* Copy Literals */
+ LZ4_wildCopy(op, anchor, op + litLength);
+ op += litLength;
+ }
+
+ _next_match:
+ /* Encode Offset */
+ LZ4_writeLE16(op, (U16)(ip - match));
+ op += 2;
+
+ /* Encode MatchLength */
+ {
+ size_t matchLength;
+
+ matchLength = LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit);
+
+ if (op + ((matchLength + 240) / 255) > oMaxMatch) {
+ /* Match description too long : reduce it */
+ matchLength = (15 - 1) + (oMaxMatch - op) * 255;
+ }
+ /*printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH);*/
+ ip += MINMATCH + matchLength;
+
+ if (matchLength >= ML_MASK) {
+ *token += ML_MASK;
+ matchLength -= ML_MASK;
+ while (matchLength >= 255) {
+ matchLength -= 255;
+ *op++ = 255;
+ }
+ *op++ = (BYTE)matchLength;
+ } else
+ *token += (BYTE)(matchLength);
+ }
+
+ anchor = ip;
+
+ /* Test end of block */
+ if (ip > mflimit)
+ break;
+ if (op > oMaxSeq)
+ break;
+
+ /* Fill table */
+ LZ4_putPosition(ip - 2, ctx, tableType, base);
+
+ /* Test next position */
+ match = LZ4_getPosition(ip, ctx, tableType, base);
+ LZ4_putPosition(ip, ctx, tableType, base);
+ if ((match + MAX_DISTANCE >= ip) && (LZ4_read32(match) == LZ4_read32(ip))) {
+ token = op++;
+ *token = 0;
+ goto _next_match;
+ }
+
+ /* Prepare next loop */
+ forwardH = LZ4_hashPosition(++ip, tableType);
+ }
+
+_last_literals:
+ /* Encode Last Literals */
+ {
+ size_t lastRunSize = (size_t)(iend - anchor);
+ if (op + 1 /* token */ + ((lastRunSize + 240) / 255) /* litLength */ + lastRunSize /* literals */ > oend) {
+ /* adapt lastRunSize to fill 'dst' */
+ lastRunSize = (oend - op) - 1;
+ lastRunSize -= (lastRunSize + 240) / 255;
+ }
+ ip = anchor + lastRunSize;
+
+ if (lastRunSize >= RUN_MASK) {
+ size_t accumulator = lastRunSize - RUN_MASK;
+ *op++ = RUN_MASK << ML_BITS;
+ for (; accumulator >= 255; accumulator -= 255)
+ *op++ = 255;
+ *op++ = (BYTE)accumulator;
+ } else {
+ *op++ = (BYTE)(lastRunSize << ML_BITS);
+ }
+ memcpy(op, anchor, lastRunSize);
+ op += lastRunSize;
+ }
+
+ /* End */
+ *srcSizePtr = (int)(((const char *)ip) - src);
+ return (int)(((char *)op) - dst);
+}
+
+static int LZ4_compress_destSize_extState(void *state, const char *src, char *dst, int *srcSizePtr, int targetDstSize)
+{
+ LZ4_resetStream((LZ4_stream_t *)state);
+
+ if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) /* compression success is guaranteed */
+ {
+ return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1);
+ } else {
+ if (*srcSizePtr < LZ4_64Klimit)
+ return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, byU16);
+ else
+ return LZ4_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize,
+ LZ4_64bits() ? byU32 : byPtr);
+ }
+}
+
+int LZ4_compress_destSize(const char *src, char *dst, int *srcSizePtr, int targetDstSize)
+{
+#if (HEAPMODE)
+ void *ctx = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */
+#else
+ LZ4_stream_t ctxBody;
+ void *ctx = &ctxBody;
+#endif
+
+ int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);
+
+#if (HEAPMODE)
+ FREEMEM(ctx);
+#endif
+ return result;
+}
+
+/********************************
+ * Streaming functions
+ ********************************/
+
+LZ4_stream_t *LZ4_createStream(void)
+{
+ LZ4_stream_t *lz4s = (LZ4_stream_t *)ALLOCATOR(8, LZ4_STREAMSIZE_U64);
+ LZ4_STATIC_ASSERT(
+ LZ4_STREAMSIZE >=
+ sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */
+ LZ4_resetStream(lz4s);
+ return lz4s;
+}
+
+void LZ4_resetStream(LZ4_stream_t *LZ4_stream) { MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t)); }
+
+int LZ4_freeStream(LZ4_stream_t *LZ4_stream)
+{
+ FREEMEM(LZ4_stream);
+ return (0);
+}
+
+#define HASH_UNIT sizeof(size_t)
+int LZ4_loadDict(LZ4_stream_t *LZ4_dict, const char *dictionary, int dictSize)
+{
+ LZ4_stream_t_internal *dict = (LZ4_stream_t_internal *)LZ4_dict;
+ const BYTE *p = (const BYTE *)dictionary;
+ const BYTE *const dictEnd = p + dictSize;
+ const BYTE *base;
+
+ if ((dict->initCheck) || (dict->currentOffset > 1 GB)) /* Uninitialized structure, or reuse overflow */
+ LZ4_resetStream(LZ4_dict);
+
+ if (dictSize < (int)HASH_UNIT) {
+ dict->dictionary = NULL;
+ dict->dictSize = 0;
+ return 0;
+ }
+
+ if ((dictEnd - p) > 64 KB)
+ p = dictEnd - 64 KB;
+ dict->currentOffset += 64 KB;
+ base = p - dict->currentOffset;
+ dict->dictionary = p;
+ dict->dictSize = (U32)(dictEnd - p);
+ dict->currentOffset += dict->dictSize;
+
+ while (p <= dictEnd - HASH_UNIT) {
+ LZ4_putPosition(p, dict->hashTable, byU32, base);
+ p += 3;
+ }
+
+ return dict->dictSize;
+}
+
+static void LZ4_renormDictT(LZ4_stream_t_internal *LZ4_dict, const BYTE *src)
+{
+ if ((LZ4_dict->currentOffset > 0x80000000) ||
+ ((size_t)LZ4_dict->currentOffset > (size_t)src)) /* address space overflow */
+ {
+ /* rescale hash table */
+ U32 delta = LZ4_dict->currentOffset - 64 KB;
+ const BYTE *dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;
+ int i;
+ for (i = 0; i < HASH_SIZE_U32; i++) {
+ if (LZ4_dict->hashTable[i] < delta)
+ LZ4_dict->hashTable[i] = 0;
+ else
+ LZ4_dict->hashTable[i] -= delta;
+ }
+ LZ4_dict->currentOffset = 64 KB;
+ if (LZ4_dict->dictSize > 64 KB)
+ LZ4_dict->dictSize = 64 KB;
+ LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;
+ }
+}
+
+int LZ4_compress_fast_continue(LZ4_stream_t *LZ4_stream, const char *source, char *dest, int inputSize,
+ int maxOutputSize, int acceleration)
+{
+ LZ4_stream_t_internal *streamPtr = (LZ4_stream_t_internal *)LZ4_stream;
+ const BYTE *const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
+
+ const BYTE *smallest = (const BYTE *)source;
+ if (streamPtr->initCheck)
+ return 0; /* Uninitialized structure detected */
+ if ((streamPtr->dictSize > 0) && (smallest > dictEnd))
+ smallest = dictEnd;
+ LZ4_renormDictT(streamPtr, smallest);
+ if (acceleration < 1)
+ acceleration = ACCELERATION_DEFAULT;
+
+ /* Check overlapping input/dictionary space */
+ {
+ const BYTE *sourceEnd = (const BYTE *)source + inputSize;
+ if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) {
+ streamPtr->dictSize = (U32)(dictEnd - sourceEnd);
+ if (streamPtr->dictSize > 64 KB)
+ streamPtr->dictSize = 64 KB;
+ if (streamPtr->dictSize < 4)
+ streamPtr->dictSize = 0;
+ streamPtr->dictionary = dictEnd - streamPtr->dictSize;
+ }
+ }
+
+ /* prefix mode : source data follows dictionary */
+ if (dictEnd == (const BYTE *)source) {
+ int result;
+ if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
+ result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32,
+ withPrefix64k, dictSmall, acceleration);
+ else
+ result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32,
+ withPrefix64k, noDictIssue, acceleration);
+ streamPtr->dictSize += (U32)inputSize;
+ streamPtr->currentOffset += (U32)inputSize;
+ return result;
+ }
+
+ /* external dictionary mode */
+ {
+ int result;
+ if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))
+ result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32,
+ usingExtDict, dictSmall, acceleration);
+ else
+ result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32,
+ usingExtDict, noDictIssue, acceleration);
+ streamPtr->dictionary = (const BYTE *)source;
+ streamPtr->dictSize = (U32)inputSize;
+ streamPtr->currentOffset += (U32)inputSize;
+ return result;
+ }
+}
+
+/* Hidden debug function, to force external dictionary mode */
+int LZ4_compress_forceExtDict(LZ4_stream_t *LZ4_dict, const char *source, char *dest, int inputSize)
+{
+ LZ4_stream_t_internal *streamPtr = (LZ4_stream_t_internal *)LZ4_dict;
+ int result;
+ const BYTE *const dictEnd = streamPtr->dictionary + streamPtr->dictSize;
+
+ const BYTE *smallest = dictEnd;
+ if (smallest > (const BYTE *)source)
+ smallest = (const BYTE *)source;
+ LZ4_renormDictT((LZ4_stream_t_internal *)LZ4_dict, smallest);
+
+ result =
+ LZ4_compress_generic(LZ4_dict, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1);
+
+ streamPtr->dictionary = (const BYTE *)source;
+ streamPtr->dictSize = (U32)inputSize;
+ streamPtr->currentOffset += (U32)inputSize;
+
+ return result;
+}
+
+int LZ4_saveDict(LZ4_stream_t *LZ4_dict, char *safeBuffer, int dictSize)
+{
+ LZ4_stream_t_internal *dict = (LZ4_stream_t_internal *)LZ4_dict;
+ const BYTE *previousDictEnd = dict->dictionary + dict->dictSize;
+
+ if ((U32)dictSize > 64 KB)
+ dictSize = 64 KB; /* useless to define a dictionary > 64 KB */
+ if ((U32)dictSize > dict->dictSize)
+ dictSize = dict->dictSize;
+
+ memmove(safeBuffer, previousDictEnd - dictSize, dictSize);
+
+ dict->dictionary = (const BYTE *)safeBuffer;
+ dict->dictSize = (U32)dictSize;
+
+ return dictSize;
+}
+
+/*******************************
+ * Decompression functions
+ *******************************/
+/*
+ * This generic decompression function cover all use cases.
+ * It shall be instantiated several times, using different sets of directives
+ * Note that it is essential this generic function is really inlined,
+ * in order to remove useless branches during compilation optimization.
+ */
+FORCE_INLINE int
+LZ4_decompress_generic(const char *const source, char *const dest, int inputSize,
+ int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */
+
+ int endOnInput, /* endOnOutputSize, endOnInputSize */
+ int partialDecoding, /* full, partial */
+ int targetOutputSize, /* only used if partialDecoding==partial */
+ int dict, /* noDict, withPrefix64k, usingExtDict */
+ const BYTE *const lowPrefix, /* == dest if dict == noDict */
+ const BYTE *const dictStart, /* only if dict==usingExtDict */
+ const size_t dictSize /* note : = 0 if noDict */
+)
+{
+ /* Local Variables */
+ const BYTE *ip = (const BYTE *)source;
+ const BYTE *const iend = ip + inputSize;
+
+ BYTE *op = (BYTE *)dest;
+ BYTE *const oend = op + outputSize;
+ BYTE *cpy;
+ BYTE *oexit = op + targetOutputSize;
+ const BYTE *const lowLimit = lowPrefix - dictSize;
+
+ const BYTE *const dictEnd = (const BYTE *)dictStart + dictSize;
+ const size_t dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4};
+ const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3};
+
+ const int safeDecode = (endOnInput == endOnInputSize);
+ const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
+
+ /* Special cases */
+ if ((partialDecoding) && (oexit > oend - MFLIMIT))
+ oexit = oend - MFLIMIT; /* targetOutputSize too high => decode everything */
+ if ((endOnInput) && (unlikely(outputSize == 0)))
+ return ((inputSize == 1) && (*ip == 0)) ? 0 : -1; /* Empty output buffer */
+ if ((!endOnInput) && (unlikely(outputSize == 0)))
+ return (*ip == 0 ? 1 : -1);
+
+ /* Main Loop */
+ while (1) {
+ unsigned token;
+ size_t length;
+ const BYTE *match;
+
+ /* get literal length */
+ token = *ip++;
+ if ((length = (token >> ML_BITS)) == RUN_MASK) {
+ unsigned s;
+ do {
+ s = *ip++;
+ length += s;
+ } while (likely((endOnInput) ? ip < iend - RUN_MASK : 1) && (s == 255));
+ if ((safeDecode) && unlikely((size_t)(op + length) < (size_t)(op)))
+ goto _output_error; /* overflow detection */
+ if ((safeDecode) && unlikely((size_t)(ip + length) < (size_t)(ip)))
+ goto _output_error; /* overflow detection */
+ }
+
+ /* copy literals */
+ cpy = op + length;
+ if (((endOnInput) &&
+ ((cpy > (partialDecoding ? oexit : oend - MFLIMIT)) || (ip + length > iend - (2 + 1 + LASTLITERALS)))) ||
+ ((!endOnInput) && (cpy > oend - COPYLENGTH))) {
+ if (partialDecoding) {
+ if (cpy > oend)
+ goto _output_error; /* Error : write attempt beyond end of output buffer */
+ if ((endOnInput) && (ip + length > iend))
+ goto _output_error; /* Error : read attempt beyond end of input buffer */
+ } else {
+ if ((!endOnInput) && (cpy != oend))
+ goto _output_error; /* Error : block decoding must stop exactly there */
+ if ((endOnInput) && ((ip + length != iend) || (cpy > oend)))
+ goto _output_error; /* Error : input must be consumed */
+ }
+ memcpy(op, ip, length);
+ ip += length;
+ op += length;
+ break; /* Necessarily EOF, due to parsing restrictions */
+ }
+ LZ4_wildCopy(op, ip, cpy);
+ ip += length;
+ op = cpy;
+
+ /* get offset */
+ match = cpy - LZ4_readLE16(ip);
+ ip += 2;
+ if ((checkOffset) && (unlikely(match < lowLimit)))
+ goto _output_error; /* Error : offset outside destination buffer */
+
+ /* get matchlength */
+ length = token & ML_MASK;
+ if (length == ML_MASK) {
+ unsigned s;
+ do {
+ if ((endOnInput) && (ip > iend - LASTLITERALS))
+ goto _output_error;
+ s = *ip++;
+ length += s;
+ } while (s == 255);
+ if ((safeDecode) && unlikely((size_t)(op + length) < (size_t)op))
+ goto _output_error; /* overflow detection */
+ }
+ length += MINMATCH;
+
+ /* check external dictionary */
+ if ((dict == usingExtDict) && (match < lowPrefix)) {
+ if (unlikely(op + length > oend - LASTLITERALS))
+ goto _output_error; /* doesn't respect parsing restriction */
+
+ if (length <= (size_t)(lowPrefix - match)) {
+ /* match can be copied as a single segment from external dictionary */
+ match = dictEnd - (lowPrefix - match);
+ memmove(op, match, length);
+ op += length;
+ } else {
+ /* match encompass external dictionary and current segment */
+ size_t copySize = (size_t)(lowPrefix - match);
+ memcpy(op, dictEnd - copySize, copySize);
+ op += copySize;
+ copySize = length - copySize;
+ if (copySize > (size_t)(op - lowPrefix)) /* overlap within current segment */
+ {
+ BYTE *const endOfMatch = op + copySize;
+ const BYTE *copyFrom = lowPrefix;
+ while (op < endOfMatch)
+ *op++ = *copyFrom++;
+ } else {
+ memcpy(op, lowPrefix, copySize);
+ op += copySize;
+ }
+ }
+ continue;
+ }
+
+ /* copy repeated sequence */
+ cpy = op + length;
+ if (unlikely((op - match) < 8)) {
+ const size_t dec64 = dec64table[op - match];
+ op[0] = match[0];
+ op[1] = match[1];
+ op[2] = match[2];
+ op[3] = match[3];
+ match += dec32table[op - match];
+ LZ4_copy4(op + 4, match);
+ op += 8;
+ match -= dec64;
+ } else {
+ LZ4_copy8(op, match);
+ op += 8;
+ match += 8;
+ }
+
+ if (unlikely(cpy > oend - 12)) {
+ if (cpy > oend - LASTLITERALS)
+ goto _output_error; /* Error : last LASTLITERALS bytes must be literals */
+ if (op < oend - 8) {
+ LZ4_wildCopy(op, match, oend - 8);
+ match += (oend - 8) - op;
+ op = oend - 8;
+ }
+ while (op < cpy)
+ *op++ = *match++;
+ } else
+ LZ4_wildCopy(op, match, cpy);
+ op = cpy; /* correction */
+ }
+
+ /* end of decoding */
+ if (endOnInput)
+ return (int)(((char *)op) - dest); /* Nb of output bytes decoded */
+ else
+ return (int)(((const char *)ip) - source); /* Nb of input bytes read */
+
+ /* Overflow error detected */
+_output_error:
+ return (int)(-(((const char *)ip) - source)) - 1;
+}
+
+int LZ4_decompress_safe(const char *source, char *dest, int compressedSize, int maxDecompressedSize)
+{
+ return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict,
+ (BYTE *)dest, NULL, 0);
+}
+
+int LZ4_decompress_safe_partial(const char *source, char *dest, int compressedSize, int targetOutputSize,
+ int maxDecompressedSize)
+{
+ return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial,
+ targetOutputSize, noDict, (BYTE *)dest, NULL, 0);
+}
+
+int LZ4_decompress_fast(const char *source, char *dest, int originalSize)
+{
+ return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k,
+ (BYTE *)(dest - 64 KB), NULL, 64 KB);
+}
+
+/* streaming decompression functions */
+
+typedef struct
+{
+ const BYTE *externalDict;
+ size_t extDictSize;
+ const BYTE *prefixEnd;
+ size_t prefixSize;
+} LZ4_streamDecode_t_internal;
+
+/*
+ * If you prefer dynamic allocation methods,
+ * LZ4_createStreamDecode()
+ * provides a pointer (void*) towards an initialized LZ4_streamDecode_t structure.
+ */
+LZ4_streamDecode_t *LZ4_createStreamDecode(void)
+{
+ LZ4_streamDecode_t *lz4s = (LZ4_streamDecode_t *)ALLOCATOR(1, sizeof(LZ4_streamDecode_t));
+ return lz4s;
+}
+
+int LZ4_freeStreamDecode(LZ4_streamDecode_t *LZ4_stream)
+{
+ FREEMEM(LZ4_stream);
+ return 0;
+}
+
+/*
+ * LZ4_setStreamDecode
+ * Use this function to instruct where to find the dictionary
+ * This function is not necessary if previous data is still available where it was decoded.
+ * Loading a size of 0 is allowed (same effect as no dictionary).
+ * Return : 1 if OK, 0 if error
+ */
+int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode, const char *dictionary, int dictSize)
+{
+ LZ4_streamDecode_t_internal *lz4sd = (LZ4_streamDecode_t_internal *)LZ4_streamDecode;
+ lz4sd->prefixSize = (size_t)dictSize;
+ lz4sd->prefixEnd = (const BYTE *)dictionary + dictSize;
+ lz4sd->externalDict = NULL;
+ lz4sd->extDictSize = 0;
+ return 1;
+}
+
+/*
+*_continue() :
+ These decoding functions allow decompression of multiple blocks in "streaming" mode.
+ Previously decoded blocks must still be available at the memory position where they were decoded.
+ If it's not possible, save the relevant part of decoded data into a safe buffer,
+ and indicate where it stands using LZ4_setStreamDecode()
+*/
+int LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode, const char *source, char *dest,
+ int compressedSize, int maxOutputSize)
+{
+ LZ4_streamDecode_t_internal *lz4sd = (LZ4_streamDecode_t_internal *)LZ4_streamDecode;
+ int result;
+
+ if (lz4sd->prefixEnd == (BYTE *)dest) {
+ result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0,
+ usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict,
+ lz4sd->extDictSize);
+ if (result <= 0)
+ return result;
+ lz4sd->prefixSize += result;
+ lz4sd->prefixEnd += result;
+ } else {
+ lz4sd->extDictSize = lz4sd->prefixSize;
+ lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;
+ result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0,
+ usingExtDict, (BYTE *)dest, lz4sd->externalDict, lz4sd->extDictSize);
+ if (result <= 0)
+ return result;
+ lz4sd->prefixSize = result;
+ lz4sd->prefixEnd = (BYTE *)dest + result;
+ }
+
+ return result;
+}
+
+int LZ4_decompress_fast_continue(LZ4_streamDecode_t *LZ4_streamDecode, const char *source, char *dest, int originalSize)
+{
+ LZ4_streamDecode_t_internal *lz4sd = (LZ4_streamDecode_t_internal *)LZ4_streamDecode;
+ int result;
+
+ if (lz4sd->prefixEnd == (BYTE *)dest) {
+ result = LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, usingExtDict,
+ lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);
+ if (result <= 0)
+ return result;
+ lz4sd->prefixSize += originalSize;
+ lz4sd->prefixEnd += originalSize;
+ } else {
+ lz4sd->extDictSize = lz4sd->prefixSize;
+ lz4sd->externalDict = (BYTE *)dest - lz4sd->extDictSize;
+ result = LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, usingExtDict,
+ (BYTE *)dest, lz4sd->externalDict, lz4sd->extDictSize);
+ if (result <= 0)
+ return result;
+ lz4sd->prefixSize = originalSize;
+ lz4sd->prefixEnd = (BYTE *)dest + originalSize;
+ }
+
+ return result;
+}
+
+/*
+Advanced decoding functions :
+*_usingDict() :
+ These decoding functions work the same as "_continue" ones,
+ the dictionary must be explicitly provided within parameters
+*/
+
+FORCE_INLINE int LZ4_decompress_usingDict_generic(const char *source, char *dest, int compressedSize, int maxOutputSize,
+ int safe, const char *dictStart, int dictSize)
+{
+ if (dictSize == 0)
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE *)dest,
+ NULL, 0);
+ if (dictStart + dictSize == dest) {
+ if (dictSize >= (int)(64 KB - 1))
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k,
+ (BYTE *)dest - 64 KB, NULL, 0);
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict,
+ (BYTE *)dest - dictSize, NULL, 0);
+ }
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict,
+ (BYTE *)dest, (const BYTE *)dictStart, dictSize);
+}
+
+int LZ4_decompress_safe_usingDict(const char *source, char *dest, int compressedSize, int maxOutputSize,
+ const char *dictStart, int dictSize)
+{
+ return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize);
+}
+
+int LZ4_decompress_fast_usingDict(const char *source, char *dest, int originalSize, const char *dictStart, int dictSize)
+{
+ return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize);
+}
+
+/* debug function */
+int LZ4_decompress_safe_forceExtDict(const char *source, char *dest, int compressedSize, int maxOutputSize,
+ const char *dictStart, int dictSize)
+{
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict,
+ (BYTE *)dest, (const BYTE *)dictStart, dictSize);
+}
+
+/***************************************************
+ * Obsolete Functions
+ ***************************************************/
+/* obsolete compression functions */
+int LZ4_compress_limitedOutput(const char *source, char *dest, int inputSize, int maxOutputSize)
+{
+ return LZ4_compress_default(source, dest, inputSize, maxOutputSize);
+}
+int LZ4_compress(const char *source, char *dest, int inputSize)
+{
+ return LZ4_compress_default(source, dest, inputSize, LZ4_compressBound(inputSize));
+}
+int LZ4_compress_limitedOutput_withState(void *state, const char *src, char *dst, int srcSize, int dstSize)
+{
+ return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1);
+}
+int LZ4_compress_withState(void *state, const char *src, char *dst, int srcSize)
+{
+ return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1);
+}
+int LZ4_compress_limitedOutput_continue(LZ4_stream_t *LZ4_stream, const char *src, char *dst, int srcSize,
+ int maxDstSize)
+{
+ return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, maxDstSize, 1);
+}
+int LZ4_compress_continue(LZ4_stream_t *LZ4_stream, const char *source, char *dest, int inputSize)
+{
+ return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1);
+}
+
+/*
+These function names are deprecated and should no longer be used.
+They are only provided here for compatibility with older user programs.
+- LZ4_uncompress is totally equivalent to LZ4_decompress_fast
+- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe
+*/
+int LZ4_uncompress(const char *source, char *dest, int outputSize)
+{
+ return LZ4_decompress_fast(source, dest, outputSize);
+}
+int LZ4_uncompress_unknownOutputSize(const char *source, char *dest, int isize, int maxOutputSize)
+{
+ return LZ4_decompress_safe(source, dest, isize, maxOutputSize);
+}
+
+/* Obsolete Streaming functions */
+
+int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; }
+
+static void LZ4_init(LZ4_stream_t_internal *lz4ds, BYTE *base)
+{
+ MEM_INIT(lz4ds, 0, LZ4_STREAMSIZE);
+ lz4ds->bufferStart = base;
+}
+
+int LZ4_resetStreamState(void *state, char *inputBuffer)
+{
+ if ((((size_t)state) & 3) != 0)
+ return 1; /* Error : pointer is not aligned on 4-bytes boundary */
+ LZ4_init((LZ4_stream_t_internal *)state, (BYTE *)inputBuffer);
+ return 0;
+}
+
+void *LZ4_create(char *inputBuffer)
+{
+ void *lz4ds = ALLOCATOR(8, LZ4_STREAMSIZE_U64);
+ LZ4_init((LZ4_stream_t_internal *)lz4ds, (BYTE *)inputBuffer);
+ return lz4ds;
+}
+
+char *LZ4_slideInputBuffer(void *LZ4_Data)
+{
+ LZ4_stream_t_internal *ctx = (LZ4_stream_t_internal *)LZ4_Data;
+ int dictSize = LZ4_saveDict((LZ4_stream_t *)LZ4_Data, (char *)ctx->bufferStart, 64 KB);
+ return (char *)(ctx->bufferStart + dictSize);
+}
+
+/* Obsolete streaming decompression functions */
+
+int LZ4_decompress_safe_withPrefix64k(const char *source, char *dest, int compressedSize, int maxOutputSize)
+{
+ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k,
+ (BYTE *)dest - 64 KB, NULL, 64 KB);
+}
+
+int LZ4_decompress_fast_withPrefix64k(const char *source, char *dest, int originalSize)
+{
+ return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k,
+ (BYTE *)dest - 64 KB, NULL, 64 KB);
+}
+
+#endif /* LZ4_COMMONDEFS_ONLY */
diff --git a/libs/fst/lz4.h b/libs/fst/lz4.h
new file mode 100644
index 000000000..929cf02ca
--- /dev/null
+++ b/libs/fst/lz4.h
@@ -0,0 +1,367 @@
+/*
+ LZ4 - Fast LZ compression algorithm
+ Header File
+ Copyright (C) 2011-2015, Yann Collet.
+
+ BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with the
+ distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ SPDX-License-Identifier: BSD-2-Clause
+
+ You can contact the author at :
+ - LZ4 source repository : https://github.com/Cyan4973/lz4
+ - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
+*/
+#pragma once
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * lz4.h provides block compression functions, and gives full buffer control to programmer.
+ * If you need to generate inter-operable compressed data (respecting LZ4 frame specification),
+ * and can let the library handle its own memory, please use lz4frame.h instead.
+ */
+
+/**************************************
+ * Version
+ **************************************/
+#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
+#define LZ4_VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */
+#define LZ4_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */
+#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR * 100 * 100 + LZ4_VERSION_MINOR * 100 + LZ4_VERSION_RELEASE)
+int LZ4_versionNumber(void);
+
+/**************************************
+ * Tuning parameter
+ **************************************/
+/*
+ * LZ4_MEMORY_USAGE :
+ * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
+ * Increasing memory usage improves compression ratio
+ * Reduced memory usage can improve speed, due to cache effect
+ * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
+ */
+#define LZ4_MEMORY_USAGE 14
+
+/**************************************
+ * Simple Functions
+ **************************************/
+
+int LZ4_compress_default(const char *source, char *dest, int sourceSize, int maxDestSize);
+int LZ4_decompress_safe(const char *source, char *dest, int compressedSize, int maxDecompressedSize);
+
+/*
+LZ4_compress_default() :
+ Compresses 'sourceSize' bytes from buffer 'source'
+ into already allocated 'dest' buffer of size 'maxDestSize'.
+ Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize).
+ It also runs faster, so it's a recommended setting.
+ If the function cannot compress 'source' into a more limited 'dest' budget,
+ compression stops *immediately*, and the function result is zero.
+ As a consequence, 'dest' content is not valid.
+ This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
+ sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE
+ maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
+ return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
+ or 0 if compression fails
+
+LZ4_decompress_safe() :
+ compressedSize : is the precise full size of the compressed block.
+ maxDecompressedSize : is the size of destination buffer, which must be already allocated.
+ return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
+ If destination buffer is not large enough, decoding will stop and output an error code (<0).
+ If the source stream is detected malformed, the function will stop decoding and return a negative result.
+ This function is protected against buffer overflow exploits, including malicious data packets.
+ It never writes outside output buffer, nor reads outside input buffer.
+*/
+
+/**************************************
+ * Advanced Functions
+ **************************************/
+#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
+#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize) / 255) + 16)
+
+/*
+LZ4_compressBound() :
+ Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
+ This function is primarily useful for memory allocation purposes (destination buffer size).
+ Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
+ Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize)
+ inputSize : max supported value is LZ4_MAX_INPUT_SIZE
+ return : maximum output size in a "worst case" scenario
+ or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE)
+*/
+int LZ4_compressBound(int inputSize);
+
+/*
+LZ4_compress_fast() :
+ Same as LZ4_compress_default(), but allows to select an "acceleration" factor.
+ The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
+ It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
+ An acceleration value of "1" is the same as regular LZ4_compress_default()
+ Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1.
+*/
+int LZ4_compress_fast(const char *source, char *dest, int sourceSize, int maxDestSize, int acceleration);
+
+/*
+LZ4_compress_fast_extState() :
+ Same compression function, just using an externally allocated memory space to store compression state.
+ Use LZ4_sizeofState() to know how much memory must be allocated,
+ and allocate it on 8-bytes boundaries (using malloc() typically).
+ Then, provide it as 'void* state' to compression function.
+*/
+int LZ4_sizeofState(void);
+int LZ4_compress_fast_extState(void *state, const char *source, char *dest, int inputSize, int maxDestSize,
+ int acceleration);
+
+/*
+LZ4_compress_destSize() :
+ Reverse the logic, by compressing as much data as possible from 'source' buffer
+ into already allocated buffer 'dest' of size 'targetDestSize'.
+ This function either compresses the entire 'source' content into 'dest' if it's large enough,
+ or fill 'dest' buffer completely with as much data as possible from 'source'.
+ *sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
+ New value is necessarily <= old value.
+ return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
+ or 0 if compression fails
+*/
+int LZ4_compress_destSize(const char *source, char *dest, int *sourceSizePtr, int targetDestSize);
+
+/*
+LZ4_decompress_fast() :
+ originalSize : is the original and therefore uncompressed size
+ return : the number of bytes read from the source buffer (in other words, the compressed size)
+ If the source stream is detected malformed, the function will stop decoding and return a negative result.
+ Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes.
+ note : This function fully respect memory boundaries for properly formed compressed data.
+ It is a bit faster than LZ4_decompress_safe().
+ However, it does not provide any protection against intentionally modified data stream (malicious input).
+ Use this function in trusted environment only (data to decode comes from a trusted source).
+*/
+int LZ4_decompress_fast(const char *source, char *dest, int originalSize);
+
+/*
+LZ4_decompress_safe_partial() :
+ This function decompress a compressed block of size 'compressedSize' at position 'source'
+ into destination buffer 'dest' of size 'maxDecompressedSize'.
+ The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,
+ reducing decompression time.
+ return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)
+ Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.
+ Always control how many bytes were decoded.
+ If the source stream is detected malformed, the function will stop decoding and return a negative result.
+ This function never writes outside of output buffer, and never reads outside of input buffer. It is
+therefore protected against malicious data packets
+*/
+int LZ4_decompress_safe_partial(const char *source, char *dest, int compressedSize, int targetOutputSize,
+ int maxDecompressedSize);
+
+/***********************************************
+ * Streaming Compression Functions
+ ***********************************************/
+#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE - 3)) + 4)
+#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(long long))
+/*
+ * LZ4_stream_t
+ * information structure to track an LZ4 stream.
+ * important : init this structure content before first use !
+ * note : only allocated directly the structure if you are statically linking LZ4
+ * If you are using liblz4 as a DLL, please use below construction methods instead.
+ */
+typedef struct
+{
+ long long table[LZ4_STREAMSIZE_U64];
+} LZ4_stream_t;
+
+/*
+ * LZ4_resetStream
+ * Use this function to init an allocated LZ4_stream_t structure
+ */
+void LZ4_resetStream(LZ4_stream_t *streamPtr);
+
+/*
+ * LZ4_createStream will allocate and initialize an LZ4_stream_t structure
+ * LZ4_freeStream releases its memory.
+ * In the context of a DLL (liblz4), please use these methods rather than the static struct.
+ * They are more future proof, in case of a change of LZ4_stream_t size.
+ */
+LZ4_stream_t *LZ4_createStream(void);
+int LZ4_freeStream(LZ4_stream_t *streamPtr);
+
+/*
+ * LZ4_loadDict
+ * Use this function to load a static dictionary into LZ4_stream.
+ * Any previous data will be forgotten, only 'dictionary' will remain in memory.
+ * Loading a size of 0 is allowed.
+ * Return : dictionary size, in bytes (necessarily <= 64 KB)
+ */
+int LZ4_loadDict(LZ4_stream_t *streamPtr, const char *dictionary, int dictSize);
+
+/*
+ * LZ4_compress_fast_continue
+ * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression
+ * ratio. Important : Previous data blocks are assumed to still be present and unmodified ! 'dst' buffer must be already
+ * allocated. If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. If
+ * not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.
+ */
+int LZ4_compress_fast_continue(LZ4_stream_t *streamPtr, const char *src, char *dst, int srcSize, int maxDstSize,
+ int acceleration);
+
+/*
+ * LZ4_saveDict
+ * If previously compressed data block is not guaranteed to remain available at its memory location
+ * save it into a safer place (char* safeBuffer)
+ * Note : you don't need to call LZ4_loadDict() afterwards,
+ * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue()
+ * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error
+ */
+int LZ4_saveDict(LZ4_stream_t *streamPtr, char *safeBuffer, int dictSize);
+
+/************************************************
+ * Streaming Decompression Functions
+ ************************************************/
+
+#define LZ4_STREAMDECODESIZE_U64 4
+#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
+typedef struct
+{
+ unsigned long long table[LZ4_STREAMDECODESIZE_U64];
+} LZ4_streamDecode_t;
+/*
+ * LZ4_streamDecode_t
+ * information structure to track an LZ4 stream.
+ * init this structure content using LZ4_setStreamDecode or memset() before first use !
+ *
+ * In the context of a DLL (liblz4) please prefer usage of construction methods below.
+ * They are more future proof, in case of a change of LZ4_streamDecode_t size in the future.
+ * LZ4_createStreamDecode will allocate and initialize an LZ4_streamDecode_t structure
+ * LZ4_freeStreamDecode releases its memory.
+ */
+LZ4_streamDecode_t *LZ4_createStreamDecode(void);
+int LZ4_freeStreamDecode(LZ4_streamDecode_t *LZ4_stream);
+
+/*
+ * LZ4_setStreamDecode
+ * Use this function to instruct where to find the dictionary.
+ * Setting a size of 0 is allowed (same effect as reset).
+ * Return : 1 if OK, 0 if error
+ */
+int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode, const char *dictionary, int dictSize);
+
+/*
+*_continue() :
+ These decoding functions allow decompression of multiple blocks in "streaming" mode.
+ Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
+ In the case of a ring buffers, decoding buffer must be either :
+ - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
+ In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
+ - Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
+ maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
+ In which case, encoding and decoding buffers do not need to be synchronized,
+ and encoding ring buffer can have any size, including small ones ( < 64 KB).
+ - _At least_ 64 KB + 8 bytes + maxBlockSize.
+ In which case, encoding and decoding buffers do not need to be synchronized,
+ and encoding ring buffer can have any size, including larger than decoding buffer.
+ Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
+ and indicate where it is saved using LZ4_setStreamDecode()
+*/
+int LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode, const char *source, char *dest,
+ int compressedSize, int maxDecompressedSize);
+int LZ4_decompress_fast_continue(LZ4_streamDecode_t *LZ4_streamDecode, const char *source, char *dest,
+ int originalSize);
+
+/*
+Advanced decoding functions :
+*_usingDict() :
+ These decoding functions work the same as
+ a combination of LZ4_setStreamDecode() followed by LZ4_decompress_x_continue()
+ They are stand-alone. They don't need nor update an LZ4_streamDecode_t structure.
+*/
+int LZ4_decompress_safe_usingDict(const char *source, char *dest, int compressedSize, int maxDecompressedSize,
+ const char *dictStart, int dictSize);
+int LZ4_decompress_fast_usingDict(const char *source, char *dest, int originalSize, const char *dictStart,
+ int dictSize);
+
+/**************************************
+ * Obsolete Functions
+ **************************************/
+/* Deprecate Warnings */
+/* Should these warnings messages be a problem,
+ it is generally possible to disable them,
+ with -Wno-deprecated-declarations for gcc
+ or _CRT_SECURE_NO_WARNINGS in Visual for example.
+ You can also define LZ4_DEPRECATE_WARNING_DEFBLOCK. */
+#ifndef LZ4_DEPRECATE_WARNING_DEFBLOCK
+#define LZ4_DEPRECATE_WARNING_DEFBLOCK
+#define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+#if (LZ4_GCC_VERSION >= 405) || defined(__clang__)
+#define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
+#elif (LZ4_GCC_VERSION >= 301)
+#define LZ4_DEPRECATED(message) __attribute__((deprecated))
+#elif defined(_MSC_VER)
+#define LZ4_DEPRECATED(message) __declspec(deprecated(message))
+#else
+#pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
+#define LZ4_DEPRECATED(message)
+#endif
+#endif /* LZ4_DEPRECATE_WARNING_DEFBLOCK */
+
+/* Obsolete compression functions */
+/* These functions are planned to start generate warnings by r131 approximately */
+int LZ4_compress(const char *source, char *dest, int sourceSize);
+int LZ4_compress_limitedOutput(const char *source, char *dest, int sourceSize, int maxOutputSize);
+int LZ4_compress_withState(void *state, const char *source, char *dest, int inputSize);
+int LZ4_compress_limitedOutput_withState(void *state, const char *source, char *dest, int inputSize, int maxOutputSize);
+int LZ4_compress_continue(LZ4_stream_t *LZ4_streamPtr, const char *source, char *dest, int inputSize);
+int LZ4_compress_limitedOutput_continue(LZ4_stream_t *LZ4_streamPtr, const char *source, char *dest, int inputSize,
+ int maxOutputSize);
+
+/* Obsolete decompression functions */
+/* These function names are completely deprecated and must no longer be used.
+ They are only provided here for compatibility with older programs.
+ - LZ4_uncompress is the same as LZ4_decompress_fast
+ - LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe
+ These function prototypes are now disabled; uncomment them only if you really need them.
+ It is highly recommended to stop using these prototypes and migrate to maintained ones */
+/* int LZ4_uncompress (const char* source, char* dest, int outputSize); */
+/* int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */
+
+/* Obsolete streaming functions; use new streaming interface whenever possible */
+LZ4_DEPRECATED("use LZ4_createStream() instead") void *LZ4_create(char *inputBuffer);
+LZ4_DEPRECATED("use LZ4_createStream() instead") int LZ4_sizeofStreamState(void);
+LZ4_DEPRECATED("use LZ4_resetStream() instead") int LZ4_resetStreamState(void *state, char *inputBuffer);
+LZ4_DEPRECATED("use LZ4_saveDict() instead") char *LZ4_slideInputBuffer(void *state);
+
+/* Obsolete streaming decoding functions */
+LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead")
+int LZ4_decompress_safe_withPrefix64k(const char *src, char *dst, int compressedSize, int maxDstSize);
+LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead")
+int LZ4_decompress_fast_withPrefix64k(const char *src, char *dst, int originalSize);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/libs/subcircuit/README b/libs/subcircuit/README
index ecaa987db..de85cdfea 100644
--- a/libs/subcircuit/README
+++ b/libs/subcircuit/README
@@ -4,7 +4,7 @@
* The SubCircuit C++11 library *
* *
* An implementation of a modified Ullmann Subgraph Isomorphism Algorithm *
- * for coarse grain logic networks. by Clifford Wolf *
+ * for coarse grain logic networks. by Claire Xenia Wolf *
* *
**************************************************************************
diff --git a/libs/subcircuit/subcircuit.cc b/libs/subcircuit/subcircuit.cc
index 4068dc09a..f38da3fcc 100644
--- a/libs/subcircuit/subcircuit.cc
+++ b/libs/subcircuit/subcircuit.cc
@@ -2,7 +2,7 @@
* SubCircuit -- An implementation of the Ullmann Subgraph Isomorphism
* algorithm for coarse grain logic networks
*
- * Copyright (C) 2013 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2013 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/libs/subcircuit/subcircuit.h b/libs/subcircuit/subcircuit.h
index 8368efab1..f2a28ecd2 100644
--- a/libs/subcircuit/subcircuit.h
+++ b/libs/subcircuit/subcircuit.h
@@ -2,7 +2,7 @@
* SubCircuit -- An implementation of the Ullmann Subgraph Isomorphism
* algorithm for coarse grain logic networks
*
- * Copyright (C) 2013 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2013 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/manual/APPNOTE_010_Verilog_to_BLIF.tex b/manual/APPNOTE_010_Verilog_to_BLIF.tex
index 0ecdf6194..16254d593 100644
--- a/manual/APPNOTE_010_Verilog_to_BLIF.tex
+++ b/manual/APPNOTE_010_Verilog_to_BLIF.tex
@@ -52,7 +52,7 @@
\begin{document}
\title{Yosys Application Note 010: \\ Converting Verilog to BLIF}
-\author{Clifford Wolf \\ November 2013}
+\author{Claire Xenia Wolf \\ November 2013}
\maketitle
\begin{abstract}
@@ -437,12 +437,12 @@ design to fit a certain need without actually touching the RTL code.
\begin{thebibliography}{9}
\bibitem{yosys}
-Clifford Wolf. The Yosys Open SYnthesis Suite. \\
-\url{http://www.clifford.at/yosys/}
+Claire Xenia Wolf. The Yosys Open SYnthesis Suite. \\
+\url{https://yosyshq.net/yosys/}
\bibitem{bigsim}
yosys-bigsim, a collection of real-world Verilog designs for regression testing purposes. \\
-\url{https://github.com/cliffordwolf/yosys-bigsim}
+\url{https://github.com/YosysHQ/yosys-bigsim}
\bibitem{navre}
Sebastien Bourdeauducq. Navr\'e AVR clone (8-bit RISC). \\
diff --git a/manual/APPNOTE_011_Design_Investigation.tex b/manual/APPNOTE_011_Design_Investigation.tex
index 9780c7833..881212fe9 100644
--- a/manual/APPNOTE_011_Design_Investigation.tex
+++ b/manual/APPNOTE_011_Design_Investigation.tex
@@ -54,7 +54,7 @@
\begin{document}
\title{Yosys Application Note 011: \\ Interactive Design Investigation}
-\author{Clifford Wolf \\ Original Version December 2013}
+\author{Claire Xenia Wolf \\ Original Version December 2013}
\maketitle
\begin{abstract}
@@ -1041,8 +1041,8 @@ framework for new algorithms alike.
\begin{thebibliography}{9}
\bibitem{yosys}
-Clifford Wolf. The Yosys Open SYnthesis Suite.
-\url{http://www.clifford.at/yosys/}
+Claire Xenia Wolf. The Yosys Open SYnthesis Suite.
+\url{https://yosyshq.net/yosys/}
\bibitem{graphviz}
Graphviz - Graph Visualization Software.
diff --git a/manual/APPNOTE_012_Verilog_to_BTOR.tex b/manual/APPNOTE_012_Verilog_to_BTOR.tex
index 1bc277876..aabdc63c4 100644
--- a/manual/APPNOTE_012_Verilog_to_BTOR.tex
+++ b/manual/APPNOTE_012_Verilog_to_BTOR.tex
@@ -52,7 +52,7 @@
\begin{document}
\title{Yosys Application Note 012: \\ Converting Verilog to BTOR}
-\author{Ahmed Irfan and Clifford Wolf \\ April 2015}
+\author{Ahmed Irfan and Claire Xenia Wolf \\ April 2015}
\maketitle
\begin{abstract}
@@ -410,8 +410,8 @@ verification benchmarks with or without memories from Verilog designs.
\begin{thebibliography}{9}
\bibitem{yosys}
-Clifford Wolf. The Yosys Open SYnthesis Suite. \\
-\url{http://www.clifford.at/yosys/}
+Claire Xenia Wolf. The Yosys Open SYnthesis Suite. \\
+\url{https://yosyshq.net/yosys/}
\bibitem{boolector}
Robert Brummayer and Armin Biere, Boolector: An Efficient SMT Solver for Bit-Vectors and Arrays\\
diff --git a/manual/CHAPTER_Auxlibs.tex b/manual/CHAPTER_Auxlibs.tex
index 440ea1375..b3041078f 100644
--- a/manual/CHAPTER_Auxlibs.tex
+++ b/manual/CHAPTER_Auxlibs.tex
@@ -22,7 +22,7 @@ ConstEval} class provided in {\tt kernel/consteval.h}.
\label{sec:SubCircuit}
The files in {\tt libs/subcircuit} provide a library for solving the subcircuit
-isomorphism problem. It is written by Clifford Wolf and based on the Ullmann
+isomorphism problem. It is written by C. Wolf and based on the Ullmann
Subgraph Isomorphism Algorithm \cite{UllmannSubgraphIsomorphism}. It is used by
the {\tt extract} pass (see {\tt help extract} or Sec.~\ref{cmd:extract}).
@@ -30,6 +30,6 @@ the {\tt extract} pass (see {\tt help extract} or Sec.~\ref{cmd:extract}).
The files in {\tt libs/ezsat} provide a library for simplifying generating CNF
formulas for SAT solvers. It also contains bindings of MiniSAT. The ezSAT
-library is written by Clifford Wolf. It is used by the {\tt sat} pass (see
+library is written by C. Wolf. It is used by the {\tt sat} pass (see
{\tt help sat} or Sec.~\ref{cmd:sat}).
diff --git a/manual/CHAPTER_CellLib.tex b/manual/CHAPTER_CellLib.tex
index d4572a88a..3c9fb31cc 100644
--- a/manual/CHAPTER_CellLib.tex
+++ b/manual/CHAPTER_CellLib.tex
@@ -287,13 +287,24 @@ The state of \B{Q} will be set to this value when the reset is active.
Note that the {\tt \$adff} and {\tt \$sdff} cells can only be used when the reset value is constant.
+D-type flip-flops with asynchronous load are represented by {\tt \$aldff} cells. As the {\tt \$dff}
+cells they have \B{CLK}, \B{D} and \B{Q} ports. In addition they also have a single-bit \B{ALOAD}
+input port for the async load enable pin, a \B{AD} input port with the same width as data for
+the async load data, and the following additional parameter:
+
+\begin{itemize}
+\item \B{ALOAD\_POLARITY} \\
+The asynchronous load is active-high if this parameter has the value {\tt 1'b1} and active-low
+if this parameter is {\tt 1'b0}.
+\end{itemize}
+
D-type flip-flops with asynchronous set and reset are represented by {\tt \$dffsr} cells.
As the {\tt \$dff} cells they have \B{CLK}, \B{D} and \B{Q} ports. In addition they also have
multi-bit \B{SET} and \B{CLR} input ports and the corresponding polarity parameters, like
{\tt \$sr} cells.
-D-type flip-flops with enable are represented by {\tt \$dffe}, {\tt \$adffe}, {\tt \$dffsre},
-{\tt \$sdffe}, and {\tt \$sdffce} cells, which are enhanced variants of {\tt \$dff}, {\tt \$adff}, {\tt \$dffsr},
+D-type flip-flops with enable are represented by {\tt \$dffe}, {\tt \$adffe}, {\tt \$aldffe}, {\tt \$dffsre},
+{\tt \$sdffe}, and {\tt \$sdffce} cells, which are enhanced variants of {\tt \$dff}, {\tt \$adff}, {\tt \$aldff}, {\tt \$dffsr},
{\tt \$sdff} (with reset over enable) and {\tt \$sdff} (with enable over reset)
cells, respectively. They have the same ports and parameters as their base cell.
In addition they also have a single-bit \B{EN} input port for the enable pin and the following parameter:
@@ -338,19 +349,19 @@ In addition to {\tt \$dlatch} ports and parameters, they also have multi-bit
\subsection{Memories}
\label{sec:memcells}
-Memories are either represented using RTLIL::Memory objects, {\tt \$memrd}, {\tt \$memwr}, and {\tt \$meminit}
-cells, or by {\tt \$mem} cells alone.
+Memories are either represented using RTLIL::Memory objects, {\tt \$memrd\_v2}, {\tt \$memwr\_v2}, and {\tt \$meminit\_v2}
+cells, or by {\tt \$mem\_v2} cells alone.
In the first alternative the RTLIL::Memory objects hold the general metadata for the memory (bit width,
-size in number of words, etc.) and for each port a {\tt \$memrd} (read port) or {\tt \$memwr} (write port)
+size in number of words, etc.) and for each port a {\tt \$memrd\_v2} (read port) or {\tt \$memwr\_v2} (write port)
cell is created. Having individual cells for read and write ports has the advantage that they can be
consolidated using resource sharing passes. In some cases this drastically reduces the number of required
-ports on the memory cell. In this alternative, memory initialization data is represented by {\tt \$meminit} cells,
+ports on the memory cell. In this alternative, memory initialization data is represented by {\tt \$meminit\_v2} cells,
which allow delaying constant folding for initialization addresses and data until after the frontend finishes.
-The {\tt \$memrd} cells have a clock input \B{CLK}, an enable input \B{EN}, an
-address input \B{ADDR}, and a data output \B{DATA}. They also have the
-following parameters:
+The {\tt \$memrd\_v2} cells have a clock input \B{CLK}, an enable input \B{EN}, an
+address input \B{ADDR}, a data output \B{DATA}, an asynchronous reset input \B{ARST},
+and a synchronous reset input \B{SRST}. They also have the following parameters:
\begin{itemize}
\item \B{MEMID} \\
@@ -360,7 +371,9 @@ The name of the RTLIL::Memory object that is associated with this read port.
The number of address bits (width of the \B{ADDR} input port).
\item \B{WIDTH} \\
-The number of data bits (width of the \B{DATA} output port).
+The number of data bits (width of the \B{DATA} output port). Note that this may be a power-of-two
+multiple of the underlying memory's width -- such ports are called wide ports and access an aligned
+group of cells at once. In this case, the corresponding low bits of \B{ADDR} must be tied to 0.
\item \B{CLK\_ENABLE} \\
When this parameter is non-zero, the clock is used. Otherwise this read port is asynchronous and
@@ -370,12 +383,37 @@ the \B{CLK} input is not used.
Clock is active on the positive edge if this parameter has the value {\tt 1'b1} and on the negative
edge if this parameter is {\tt 1'b0}.
-\item \B{TRANSPARENT} \\
-If this parameter is set to {\tt 1'b1}, a read and write to the same address in the same cycle will
-return the new value. Otherwise the old value is returned.
+\item \B{TRANSPARENCY\_MASK} \\
+This parameter is a bitmask of write ports that this read port is transparent with. The bits
+of this parameter are indexed by the write port's \B{PORTID} parameter. Transparency can only be
+enabled between synchronous ports sharing a clock domain. When transparency is enabled for a given
+port pair, a read and write to the same address in the same cycle will return the new value.
+Otherwise the old value is returned.
+
+\item \B{COLLISION\_X\_MASK} \\
+This parameter is a bitmask of write ports that have undefined collision behavior with this port.
+The bits of this parameter are indexed by the write port's \B{PORTID} parameter. This behavior can only be
+enabled between synchronous ports sharing a clock domain. When undefined collision is enabled for a given
+port pair, a read and write to the same address in the same cycle will return the undefined (all-X) value.
+This option is exclusive (for a given port pair) with the transparency option.
+
+\item \B{ARST\_VALUE} \\
+Whenever the \B{ARST} input is asserted, the data output will be reset to this value.
+Only used for synchronous ports.
+
+\item \B{SRST\_VALUE} \\
+Whenever the \B{SRST} input is synchronously asserted, the data output will be reset to this value.
+Only used for synchronous ports.
+
+\item \B{INIT\_VALUE} \\
+The initial value of the data output, for synchronous ports.
+
+\item \B{CE\_OVER\_SRST} \\
+If this parameter is non-zero, the \B{SRST} input is only recognized when \B{EN} is true.
+Otherwise, \B{SRST} is recognized regardless of \B{EN}.
\end{itemize}
-The {\tt \$memwr} cells have a clock input \B{CLK}, an enable input \B{EN} (one
+The {\tt \$memwr\_v2} cells have a clock input \B{CLK}, an enable input \B{EN} (one
enable bit for each data bit), an address input \B{ADDR} and a data input
\B{DATA}. They also have the following parameters:
@@ -387,7 +425,9 @@ The name of the RTLIL::Memory object that is associated with this write port.
The number of address bits (width of the \B{ADDR} input port).
\item \B{WIDTH} \\
-The number of data bits (width of the \B{DATA} output port).
+The number of data bits (width of the \B{DATA} output port). Like with {\tt \$memrd\_v2} cells,
+the width is allowed to be any power-of-two multiple of memory width, with the corresponding
+restriction on address.
\item \B{CLK\_ENABLE} \\
When this parameter is non-zero, the clock is used. Otherwise this write port is asynchronous and
@@ -397,12 +437,20 @@ the \B{CLK} input is not used.
Clock is active on positive edge if this parameter has the value {\tt 1'b1} and on the negative
edge if this parameter is {\tt 1'b0}.
-\item \B{PRIORITY} \\
-The cell with the higher integer value in this parameter wins a write conflict.
+\item \B{PORTID} \\
+An identifier for this write port, used to index write port bit mask parameters.
+
+\item \B{PRIORITY\_MASK} \\
+This parameter is a bitmask of write ports that this write port has priority over in case of writing
+to the same address. The bits of this parameter are indexed by the other write port's \B{PORTID} parameter.
+Write ports can only have priority over write ports with lower port ID. When two ports write to the same
+address and neither has priority over the other, the result is undefined. Priority can only be set between
+two synchronous ports sharing the same clock domain.
\end{itemize}
-The {\tt \$meminit} cells have an address input \B{ADDR} and a data input \B{DATA}, with the width
-of the \B{DATA} port equal to \B{WIDTH} parameter times \B{WORDS} parameter. Both of the inputs
+The {\tt \$meminit\_v2} cells have an address input \B{ADDR}, a data input \B{DATA}, with the width
+of the \B{DATA} port equal to \B{WIDTH} parameter times \B{WORDS} parameter, and a bit enable mask input
+\B{EN} with width equal to \B{WIDTH} parameter. All three of the inputs
must resolve to a constant for synthesis to succeed.
\begin{itemize}
@@ -423,17 +471,17 @@ The cell with the higher integer value in this parameter wins an initialization
\end{itemize}
The HDL frontend models a memory using RTLIL::Memory objects and asynchronous
-{\tt \$memrd} and {\tt \$memwr} cells. The {\tt memory} pass (i.e.~its various sub-passes) migrates
-{\tt \$dff} cells into the {\tt \$memrd} and {\tt \$memwr} cells making them synchronous, then
-converts them to a single {\tt \$mem} cell and (optionally) maps this cell type
+{\tt \$memrd\_v2} and {\tt \$memwr\_v2} cells. The {\tt memory} pass (i.e.~its various sub-passes) migrates
+{\tt \$dff} cells into the {\tt \$memrd\_v2} and {\tt \$memwr\_v2} cells making them synchronous, then
+converts them to a single {\tt \$mem\_v2} cell and (optionally) maps this cell type
to {\tt \$dff} cells for the individual words and multiplexer-based address decoders for the read and
-write interfaces. When the last step is disabled or not possible, a {\tt \$mem} cell is left in the design.
+write interfaces. When the last step is disabled or not possible, a {\tt \$mem\_v2} cell is left in the design.
-The {\tt \$mem} cell provides the following parameters:
+The {\tt \$mem\_v2} cell provides the following parameters:
\begin{itemize}
\item \B{MEMID} \\
-The name of the original RTLIL::Memory object that became this {\tt \$mem} cell.
+The name of the original RTLIL::Memory object that became this {\tt \$mem\_v2} cell.
\item \B{SIZE} \\
The number of words in the memory.
@@ -450,26 +498,56 @@ The initial memory contents.
\item \B{RD\_PORTS} \\
The number of read ports on this memory cell.
+\item \B{RD\_WIDE\_CONTINUATION} \\
+This parameter is \B{RD\_PORTS} bits wide, containing a bitmask of ``wide continuation'' read ports.
+Such ports are used to represent the extra data bits of wide ports in the combined cell, and must
+have all control signals identical with the preceding port, except for address, which must have
+the proper sub-cell address encoded in the low bits.
+
\item \B{RD\_CLK\_ENABLE} \\
This parameter is \B{RD\_PORTS} bits wide, containing a clock enable bit for each read port.
\item \B{RD\_CLK\_POLARITY} \\
This parameter is \B{RD\_PORTS} bits wide, containing a clock polarity bit for each read port.
-\item \B{RD\_TRANSPARENT} \\
-This parameter is \B{RD\_PORTS} bits wide, containing a transparent bit for each read port.
+\item \B{RD\_TRANSPARENCY\_MASK} \\
+This parameter is \B{RD\_PORTS*WR\_PORTS} bits wide, containing a concatenation of all
+\B{TRANSPARENCY\_MASK} values of the original {\tt \$memrd\_v2} cells.
+
+\item \B{RD\_COLLISION\_X\_MASK} \\
+This parameter is \B{RD\_PORTS*WR\_PORTS} bits wide, containing a concatenation of all
+\B{COLLISION\_X\_MASK} values of the original {\tt \$memrd\_v2} cells.
+
+\item \B{RD\_CE\_OVER\_SRST} \\
+This parameter is \B{RD\_PORTS} bits wide, determining relative synchronous reset and enable priority for each read port.
+
+\item \B{RD\_INIT\_VALUE} \\
+This parameter is \B{RD\_PORTS*WIDTH} bits wide, containing the initial value for each synchronous read port.
+
+\item \B{RD\_ARST\_VALUE} \\
+This parameter is \B{RD\_PORTS*WIDTH} bits wide, containing the asynchronous reset value for each synchronous read port.
+
+\item \B{RD\_SRST\_VALUE} \\
+This parameter is \B{RD\_PORTS*WIDTH} bits wide, containing the synchronous reset value for each synchronous read port.
\item \B{WR\_PORTS} \\
The number of write ports on this memory cell.
+\item \B{WR\_WIDE\_CONTINUATION} \\
+This parameter is \B{WR\_PORTS} bits wide, containing a bitmask of ``wide continuation'' write ports.
+
\item \B{WR\_CLK\_ENABLE} \\
This parameter is \B{WR\_PORTS} bits wide, containing a clock enable bit for each write port.
\item \B{WR\_CLK\_POLARITY} \\
This parameter is \B{WR\_PORTS} bits wide, containing a clock polarity bit for each write port.
+
+\item \B{WR\_PRIORITY\_MASK} \\
+This parameter is \B{WR\_PORTS*WR\_PORTS} bits wide, containing a concatenation of all
+\B{PRIORITY\_MASK} values of the original {\tt \$memwr\_v2} cells.
\end{itemize}
-The {\tt \$mem} cell has the following ports:
+The {\tt \$mem\_v2} cell has the following ports:
\begin{itemize}
\item \B{RD\_CLK} \\
@@ -484,6 +562,12 @@ This input is \B{RD\_PORTS}*\B{ABITS} bits wide, containing all address signals
\item \B{RD\_DATA} \\
This input is \B{RD\_PORTS}*\B{WIDTH} bits wide, containing all data signals for the read ports.
+\item \B{RD\_ARST} \\
+This input is \B{RD\_PORTS} bits wide, containing all asynchronous reset signals for the read ports.
+
+\item \B{RD\_SRST} \\
+This input is \B{RD\_PORTS} bits wide, containing all synchronous reset signals for the read ports.
+
\item \B{WR\_CLK} \\
This input is \B{WR\_PORTS} bits wide, containing all clock signals for the write ports.
@@ -497,11 +581,11 @@ This input is \B{WR\_PORTS}*\B{ABITS} bits wide, containing all address signals
This input is \B{WR\_PORTS}*\B{WIDTH} bits wide, containing all data signals for the write ports.
\end{itemize}
-The {\tt memory\_collect} pass can be used to convert discrete {\tt \$memrd}, {\tt \$memwr}, and {\tt \$meminit} cells
-belonging to the same memory to a single {\tt \$mem} cell, whereas the {\tt memory\_unpack} pass performs the inverse operation.
+The {\tt memory\_collect} pass can be used to convert discrete {\tt \$memrd\_v2}, {\tt \$memwr\_v2}, and {\tt \$meminit\_v2} cells
+belonging to the same memory to a single {\tt \$mem\_v2} cell, whereas the {\tt memory\_unpack} pass performs the inverse operation.
The {\tt memory\_dff} pass can combine asynchronous memory ports that are fed by or feeding registers into synchronous memory ports.
-The {\tt memory\_bram} pass can be used to recognize {\tt \$mem} cells that can be implemented with a block RAM resource on an FPGA.
-The {\tt memory\_map} pass can be used to implement {\tt \$mem} cells as basic logic: word-wide DFFs and address decoders.
+The {\tt memory\_bram} pass can be used to recognize {\tt \$mem\_v2} cells that can be implemented with a block RAM resource on an FPGA.
+The {\tt memory\_map} pass can be used to implement {\tt \$mem\_v2} cells as basic logic: word-wide DFFs and address decoders.
\subsection{Finite State Machines}
diff --git a/manual/CHAPTER_Overview.tex b/manual/CHAPTER_Overview.tex
index 83db5aac7..50a56137c 100644
--- a/manual/CHAPTER_Overview.tex
+++ b/manual/CHAPTER_Overview.tex
@@ -350,8 +350,9 @@ to update {\tt \textbackslash{}q}.
An RTLIL::Process is a container for zero or more RTLIL::SyncRule objects and
exactly one RTLIL::CaseRule object, which is called the {\it root case}.
-An RTLIL::SyncRule object contains an (optional) synchronization condition (signal and edge-type) and zero or
-more assignments (RTLIL::SigSig). The {\tt always} synchronization condition is used to break combinatorial
+An RTLIL::SyncRule object contains an (optional) synchronization condition (signal and edge-type), zero or
+more assignments (RTLIL::SigSig), and zero or more memory writes (RTLIL::MemWriteAction).
+The {\tt always} synchronization condition is used to break combinatorial
loops when a latch should be inferred instead.
An RTLIL::CaseRule is a container for zero or more assignments (RTLIL::SigSig)
diff --git a/manual/CHAPTER_Prog.tex b/manual/CHAPTER_Prog.tex
index 3cbc95a19..49432f73b 100644
--- a/manual/CHAPTER_Prog.tex
+++ b/manual/CHAPTER_Prog.tex
@@ -5,13 +5,15 @@
This chapter contains some bits and pieces of information about programming
yosys extensions. Also consult the section on programming in the ``Yosys
Presentation'' (can be downloaded from the Yosys website as PDF) and don't
-be afraid to ask questions on the Yosys Subreddit.
+be afraid to ask questions on the YosysHQ Slack.
-\section{The ``CodingReadme'' File}
+\section{Guidelines}
-The following is an excerpt of the {\tt CodingReadme} file from the Yosys source tree.
+The {\tt guidelines} directory contains notes on various aspects of Yosys development. The files {\tt GettingStarted} and {\tt CodingStyle} may be of particular interest, and are reproduced here.
-\lstinputlisting[title=CodingReadme,rangeprefix=--,rangesuffix=--,includerangemarker=false,linerange=snip-snap,numbers=left,frame=single]{../CodingReadme}
+\lstinputlisting[title=GettingStarted,numbers=left,frame=single]{../guidelines/GettingStarted}
+
+\lstinputlisting[title=CodingStyle,numbers=left,frame=single]{../guidelines/CodingStyle}
\section{The ``stubsnets'' Example Module}
@@ -23,4 +25,3 @@ The following is the complete code of the ``stubsnets'' example module. It is in
\lstinputlisting[title=Makefile,numbers=left,frame=single,language=make]{CHAPTER_Prog/Makefile}
\lstinputlisting[title=test.v,numbers=left,frame=single,language=Verilog]{CHAPTER_Prog/test.v}
-
diff --git a/manual/CHAPTER_StateOfTheArt/simlib_yosys.v b/manual/CHAPTER_StateOfTheArt/simlib_yosys.v
index 454c9a83f..ec209fa02 100644
--- a/manual/CHAPTER_StateOfTheArt/simlib_yosys.v
+++ b/manual/CHAPTER_StateOfTheArt/simlib_yosys.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/manual/CHAPTER_TextRtlil.tex b/manual/CHAPTER_TextRtlil.tex
index 5615a8707..67eade8bf 100644
--- a/manual/CHAPTER_TextRtlil.tex
+++ b/manual/CHAPTER_TextRtlil.tex
@@ -217,7 +217,7 @@ Cells perform functions on input signals. See Chap.~\ref{chapter:celllib} for a
\begin{indentgrammar}{<cell-body-stmt>}
<cell> ::= <attr-stmt>$*$ <cell-stmt> <cell-body-stmt>$*$ <cell-end-stmt>
-<cell-stmt> ::= "cell" <cell-id> <cell-type> <eol>
+<cell-stmt> ::= "cell" <cell-type> <cell-id> <eol>
<cell-id> ::= <id>
diff --git a/manual/CHAPTER_Verilog.tex b/manual/CHAPTER_Verilog.tex
index d4cc55647..c1ecc0397 100644
--- a/manual/CHAPTER_Verilog.tex
+++ b/manual/CHAPTER_Verilog.tex
@@ -503,6 +503,8 @@ signal to the temporary signal in its \lstinline[language=C++]{RTLIL::CaseRule}/
\item Finally a \lstinline[language=C++]{RTLIL::SyncRule} is created for the \lstinline[language=C++]{RTLIL::Process} that
assigns the temporary signals for the final values to the actual signals.
%
+\item A process may also contain memory writes. A \lstinline[language=C++]{RTLIL::MemWriteAction} is created for each of them.
+%
\item Calls to \lstinline[language=C++]{AST::AstNode::genRTLIL()} are generated for right hand sides as needed. When blocking
assignments are used, \lstinline[language=C++]{AST::AstNode::genRTLIL()} is configured using global variables to use
the temporary signals that hold the correct intermediate values whenever one of the previously assigned signals is used
@@ -821,6 +823,9 @@ the \C{RTLIL::SyncRule}s that describe the output registers.
This pass replaces the \C{RTLIL::SyncRule}s to d-type flip-flops (with
asynchronous resets if necessary).
%
+\item {\tt proc\_dff} \\
+This pass replaces the \C{RTLIL::MemWriteActions}s with {\tt \$memwr} cells.
+%
\item {\tt proc\_clean} \\
A final call to {\tt proc\_clean} removes the now empty \C{RTLIL::Process} objects.
\end{itemize}
diff --git a/manual/PRESENTATION_ExAdv.tex b/manual/PRESENTATION_ExAdv.tex
index ef8f64cec..6a426ff2b 100644
--- a/manual/PRESENTATION_ExAdv.tex
+++ b/manual/PRESENTATION_ExAdv.tex
@@ -890,7 +890,7 @@ Questions?
\bigskip
\bigskip
\begin{center}
-\url{http://www.clifford.at/yosys/}
+\url{https://yosyshq.net/yosys/}
\end{center}
\end{frame}
diff --git a/manual/PRESENTATION_ExOth.tex b/manual/PRESENTATION_ExOth.tex
index 73f8bea2e..3f5113e3c 100644
--- a/manual/PRESENTATION_ExOth.tex
+++ b/manual/PRESENTATION_ExOth.tex
@@ -221,7 +221,7 @@ Questions?
\bigskip
\bigskip
\begin{center}
-\url{http://www.clifford.at/yosys/}
+\url{https://yosyshq.net/yosys/}
\end{center}
\end{frame}
diff --git a/manual/PRESENTATION_ExSyn.tex b/manual/PRESENTATION_ExSyn.tex
index 655720ebc..d7cfdc6f2 100644
--- a/manual/PRESENTATION_ExSyn.tex
+++ b/manual/PRESENTATION_ExSyn.tex
@@ -509,7 +509,7 @@ Questions?
\bigskip
\bigskip
\begin{center}
-\url{http://www.clifford.at/yosys/}
+\url{https://yosyshq.net/yosys/}
\end{center}
\end{frame}
diff --git a/manual/PRESENTATION_Intro.tex b/manual/PRESENTATION_Intro.tex
index af561d01b..1c3b79fa0 100644
--- a/manual/PRESENTATION_Intro.tex
+++ b/manual/PRESENTATION_Intro.tex
@@ -260,7 +260,7 @@ The following slides cover an example project. This project contains three files
\end{itemize}
\vfill
Direct link to the files: \\ \footnotesize
-\url{https://github.com/cliffordwolf/yosys/tree/master/manual/PRESENTATION_Intro}
+\url{https://github.com/YosysHQ/yosys/tree/master/manual/PRESENTATION_Intro}
\end{frame}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -476,7 +476,7 @@ Command reference:
\begin{itemize}
\item Use ``{\tt help}'' for a command list and ``{\tt help \it command}'' for details.
\item Or run ``{\tt yosys -H}'' or ``{\tt yosys -h \it command}''.
-\item Or go to \url{http://www.clifford.at/yosys/documentation.html}.
+\item Or go to \url{https://yosyshq.net/yosys/documentation.html}.
\end{itemize}
\bigskip
@@ -806,7 +806,7 @@ but also formal verification, reverse engineering, ...}
\begin{itemize}
\item Ongoing PhD project on coarse grain synthesis \\
{\setlength{\parindent}{0.5cm}\footnotesize
-Johann Glaser and Clifford Wolf. Methodology and Example-Driven Interconnect
+Johann Glaser and C. Wolf. Methodology and Example-Driven Interconnect
Synthesis for Designing Heterogeneous Coarse-Grain Reconfigurable
Architectures. In Jan Haase, editor, \it Models, Methods, and Tools for Complex
Chip Design. Lecture Notes in Electrical Engineering. Volume 265, 2014, pp
@@ -913,11 +913,11 @@ control logic because it is simpler than setting up a commercial flow.
\begin{frame}{\subsecname}
\begin{itemize}
\item Website: \\
-\smallskip\hskip1cm\url{http://www.clifford.at/yosys/}
+\smallskip\hskip1cm\url{https://yosyshq.net/yosys/}
\bigskip
\item Manual, Command Reference, Application Notes: \\
-\smallskip\hskip1cm\url{http://www.clifford.at/yosys/documentation.html}
+\smallskip\hskip1cm\url{https://yosyshq.net/yosys/documentation.html}
\bigskip
\item Instead of a mailing list we have a SubReddit: \\
@@ -925,7 +925,7 @@ control logic because it is simpler than setting up a commercial flow.
\bigskip
\item Direct link to the source code: \\
-\smallskip\hskip1cm\url{https://github.com/cliffordwolf/yosys}
+\smallskip\hskip1cm\url{https://github.com/YosysHQ/yosys}
\end{itemize}
\end{frame}
@@ -950,7 +950,7 @@ Questions?
\bigskip
\bigskip
\begin{center}
-\url{http://www.clifford.at/yosys/}
+\url{https://yosyshq.net/yosys/}
\end{center}
\end{frame}
diff --git a/manual/PRESENTATION_Prog.tex b/manual/PRESENTATION_Prog.tex
index 3b61361af..b0390cb99 100644
--- a/manual/PRESENTATION_Prog.tex
+++ b/manual/PRESENTATION_Prog.tex
@@ -590,7 +590,7 @@ Questions?
\bigskip
\bigskip
\begin{center}
-\url{http://www.clifford.at/yosys/}
+\url{https://yosyshq.net/yosys/}
\end{center}
\end{frame}
diff --git a/manual/PRESENTATION_Prog/Makefile b/manual/PRESENTATION_Prog/Makefile
index 7e3cf814b..2ac8e5bed 100644
--- a/manual/PRESENTATION_Prog/Makefile
+++ b/manual/PRESENTATION_Prog/Makefile
@@ -16,6 +16,6 @@ test1.log: my_cmd.so
mv test1.log_new test1.log
test2.log: my_cmd.so
- ../../yosys -Ql test2.log_new -m ./my_cmd.so -p 'test2' sigmap_test.v
+ ../../yosys -Ql test2.log_new -m ./my_cmd.so -p 'hierarchy -top test; test2' sigmap_test.v
mv test2.log_new test2.log
diff --git a/manual/command-reference-manual.tex b/manual/command-reference-manual.tex
index 988f034b4..1aa0facb5 100644
--- a/manual/command-reference-manual.tex
+++ b/manual/command-reference-manual.tex
@@ -22,11 +22,11 @@ library to a target architecture.
if no -script parameter is given, the following scripts are used:
- for -liberty without -constr:
+ for -liberty/-genlib without -constr:
strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f;
&nf {D}; &put
- for -liberty with -constr:
+ for -liberty/-genlib with -constr:
strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f;
&nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p
@@ -49,10 +49,10 @@ library to a target architecture.
use different default scripts that are slightly faster (at the cost
of output quality):
- for -liberty without -constr:
+ for -liberty/-genlib without -constr:
strash; dretime; map {D}
- for -liberty with -constr:
+ for -liberty/-genlib with -constr:
strash; dretime; map {D}; buffer; upsize {D}; dnsize {D};
stime -p
@@ -60,7 +60,7 @@ library to a target architecture.
strash; dretime; if
for -sop:
- strash; dretime; cover -I {I} -P {P}
+ strash; dretime; cover {I} {P}
otherwise:
strash; dretime; map
@@ -69,8 +69,13 @@ library to a target architecture.
generate netlists for the specified cell library (using the liberty
file format).
+ -genlib <file>
+ generate netlists for the specified cell library (using the SIS Genlib
+ file format).
+
-constr <file>
- pass this file with timing constraints to ABC. use with -liberty.
+ pass this file with timing constraints to ABC.
+ use with -liberty/-genlib.
a constr file contains two lines:
set_driving_cell <cell_name>
@@ -167,7 +172,7 @@ library to a target architecture.
preserve naming by an equivalence check between the original and post-ABC
netlists (experimental).
-When neither -liberty nor -lut is used, the Yosys standard cell library is
+When no target cell library is specified the Yosys standard cell library is
loaded into ABC before the ABC script is executed.
Note that this is a logic optimization pass within Yosys that is calling ABC
@@ -241,8 +246,8 @@ architecture. Only fully-selected modules are supported.
specified).
-dff
- also pass $_ABC9_FF_ cells through to ABC. modules with many clock
- domains are marked as such and automatically partitioned by ABC.
+ also pass $_DFF_[NP]_ cells through to ABC. modules with many clock
+ domains are supported and automatically partitioned by ABC.
-nocleanup
when this option is used, the temporary files created by this pass
@@ -265,28 +270,64 @@ externally if you want to use ABC to convert your design into another format.
[1] http://www.eecs.berkeley.edu/~alanmi/abc/
+ check:
+ abc9_ops -check [-dff] (option if -dff)
+
+ map:
+ abc9_ops -prep_hier [-dff] (option if -dff)
+ scc -specify -set_attr abc9_scc_id {}
+ abc9_ops -prep_bypass [-prep_dff] (option if -dff)
+ design -stash $abc9
+ design -load $abc9_map
+ proc
+ wbflip
+ techmap -wb -map %$abc9 -map +/techmap.v A:abc9_flop
+ opt -nodffe -nosdff
+ abc9_ops -prep_dff_submod (only if -dff)
+ setattr -set submod "$abc9_flop" t:$_DFF_?_ %ci* %co* t:$_DFF_?_ %d (only if -dff)
+ submod (only if -dff)
+ setattr -mod -set whitebox 1 -set abc9_flop 1 -set abc9_box 1 *_$abc9_flop (only if -dff)
+ foreach module in design
+ rename <module-name>_$abc9_flop _TECHMAP_REPLACE_ (only if -dff)
+ abc9_ops -prep_dff_unmap (only if -dff)
+ design -copy-to $abc9 =*_$abc9_flop (only if -dff)
+ delete =*_$abc9_flop (only if -dff)
+ design -stash $abc9_map
+ design -load $abc9
+ design -delete $abc9
+ techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v [-D DFF] (option if -dff)
+ design -delete $abc9_map
+
pre:
- abc9_ops -check
- scc -set_attr abc9_scc_id {}
- abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff] (option for -dff)
+ read_verilog -icells -lib -specify +/abc9_model.v
+ abc9_ops -break_scc -prep_delays -prep_xaiger [-dff] (option for -dff)
abc9_ops -prep_lut <maxlut> (skip if -lut or -luts)
- abc9_ops -prep_box [-dff] (skip if -box)
- select -set abc9_holes A:abc9_holes
- flatten -wb @abc9_holes
- techmap @abc9_holes
- abc9_ops -prep_dff (only if -dff)
- opt -purge @abc9_holes
+ abc9_ops -prep_box (skip if -box)
+ design -stash $abc9
+ design -load $abc9_holes
+ techmap -wb -map %$abc9 -map +/techmap.v
+ opt -purge
aigmap
- wbflip @abc9_holes
+ design -stash $abc9_holes
+ design -load $abc9
+ design -delete $abc9
- map:
+ exe:
+ aigmap
foreach module in selection
abc9_ops -write_lut <abc-temp-dir>/input.lut (skip if '-lut' or '-luts')
- abc9_ops -write_box <abc-temp-dir>/input.box
- write_xaiger -map <abc-temp-dir>/input.sym <abc-temp-dir>/input.xaig
- abc9_exe [options] -cwd <abc-temp-dir> [-lut <abc-temp-dir>/input.lut] -box <abc-temp-dir>/input.box
+ abc9_ops -write_box <abc-temp-dir>/input.box (skip if '-box')
+ write_xaiger -map <abc-temp-dir>/input.sym [-dff] <abc-temp-dir>/input.xaig
+ abc9_exe [options] -cwd <abc-temp-dir> -lut [<abc-temp-dir>/input.lut] -box [<abc-temp-dir>/input.box]
read_aiger -xaiger -wideports -module_name <module-name>$abc9 -map <abc-temp-dir>/input.sym <abc-temp-dir>/output.aig
- abc9_ops -reintegrate
+ abc9_ops -reintegrate [-dff]
+
+ unmap:
+ techmap -wb -map %$abc9_unmap -map +/abc9_unmap.v
+ design -delete $abc9_unmap
+ design -delete $abc9_holes
+ delete =*_$abc9_byp
+ setattr -mod -unset abc9_box_id
\end{lstlisting}
\section{abc9\_exe -- use ABC9 for technology mapping}
@@ -375,30 +416,56 @@ the `abc9' script pass. Only fully-selected modules are supported.
check that the design is valid, e.g. (* abc9_box_id *) values are unique,
(* abc9_carry *) is only given for one input/output port, etc.
+ -prep_hier
+ derive all used (* abc9_box *) or (* abc9_flop *) (if -dff option)
+ whitebox modules. with (* abc9_flop *) modules, only those containing
+ $dff/$_DFF_[NP]_ cells with zero initial state -- due to an ABC limitation
+ -- will be derived.
+
+ -prep_bypass
+ create techmap rules in the '$abc9_map' and '$abc9_unmap' designs for
+ bypassing sequential (* abc9_box *) modules using a combinatorial box
+ (named *_$abc9_byp). bypassing is necessary if sequential elements (e.g.
+ $dff, $mem, etc.) are discovered inside so that any combinatorial paths
+ will be correctly captured. this bypass box will only contain ports that
+ are referenced by a simple path declaration ($specify2 cell) inside a
+ specify block.
+
+ -prep_dff
+ select all (* abc9_flop *) modules instantiated in the design and store
+ in the named selection '$abc9_flops'.
+
+ -prep_dff_submod
+ within (* abc9_flop *) modules, rewrite all edge-sensitive path
+ declarations and $setup() timing checks ($specify3 and $specrule cells)
+ that share a 'DST' port with the $_DFF_[NP]_.Q port from this 'Q' port to
+ the DFF's 'D' port. this is to prepare such specify cells to be moved
+ into the flop box.
+
+ -prep_dff_unmap
+ populate the '$abc9_unmap' design with techmap rules for mapping *_$abc9_flop
+ cells back into their derived cell types (where the rules created by
+ -prep_hier will then map back to the original cell with parameters).
+
-prep_delays
insert `$__ABC9_DELAY' blackbox cells into the design to account for
certain required times.
- -mark_scc
+ -break_scc
for an arbitrarily chosen cell in each unique SCC of each selected module
- (tagged with an (* abc9_scc_id = <int> *) attribute), temporarily mark all
- wires driven by this cell's outputs with a (* keep *) attribute in order
- to break the SCC. this temporary attribute will be removed on -reintegrate.
+ (tagged with an (* abc9_scc_id = <int> *) attribute) interrupt all wires
+ driven by this cell's outputs with a temporary $__ABC9_SCC_BREAKER cell
+ to break the SCC.
-prep_xaiger
prepare the design for XAIGER output. this includes computing the
- topological ordering of ABC9 boxes, as well as preparing the
- '<module-name>$holes' module that contains the logic behaviour of ABC9
- whiteboxes.
+ topological ordering of ABC9 boxes, as well as preparing the '$abc9_holes'
+ design that contains the logic behaviour of ABC9 whiteboxes.
-dff
consider flop cells (those instantiating modules marked with (* abc9_flop *))
during -prep_{delays,xaiger,box}.
- -prep_dff
- compute the clock domain and initial value of each flop in the design.
- process the '$holes' module to support clock-enable functionality.
-
-prep_lut <maxlut>
pre-compute the lut library by analysing all modules marked with
(* abc9_lut=<area> *).
@@ -522,8 +589,6 @@ This pass assumes negative hold time for the async FF inputs. For example when
a reset deasserts with the clock edge, then the FF output will still drive the
reset value in the next cycle regardless of the data-in value at the time of
the clock edge.
-
-Currently only $adff, $dffsr, and $dlatch cells are supported by this pass.
\end{lstlisting}
\section{attrmap -- renaming attributes}
@@ -606,27 +671,35 @@ Convert modules into blackbox modules (remove contents and set the blackbox
module attribute).
\end{lstlisting}
+\section{bmuxmap -- transform \$bmux cells to trees of \$mux cells}
+\label{cmd:bmuxmap}
+\begin{lstlisting}[numbers=left,frame=single]
+ bmuxmap [selection]
+
+This pass transforms $bmux cells to trees of $mux cells.
+\end{lstlisting}
+
\section{bugpoint -- minimize testcases}
\label{cmd:bugpoint}
\begin{lstlisting}[numbers=left,frame=single]
- bugpoint [options]
+ bugpoint [options] [-script <filename> | -command "<command>"]
-This command minimizes testcases that crash Yosys. It removes an arbitrary part
-of the design and recursively invokes Yosys with a given script, repeating these
-steps while it can find a smaller design that still causes a crash. Once this
-command finishes, it replaces the current design with the smallest testcase it
-was able to produce.
+This command minimizes the current design that is known to crash Yosys with the
+given script into a smaller testcase. It does this by removing an arbitrary part
+of the design and recursively invokes a new Yosys process with this modified design
+and the same script, repeating these steps while it can find a smaller design that
+still causes a crash. Once this command finishes, it replaces the current design
+with the smallest testcase it was able to produce.
+In order to save the reduced testcase you must write this out to a file with
+another command after `bugpoint` like `write_rtlil` or `write_verilog`.
-It is possible to specify the kinds of design part that will be removed. If none
-are specified, all parts of design will be removed.
+ -script <filename> | -command "<command>"
+ use this script file or command to crash Yosys. required.
-yosys <filename>
use this Yosys binary. if not specified, `yosys` is used.
- -script <filename>
- use this script to crash Yosys. required.
-
- -grep <string>
+ -grep "<string>"
only consider crashes that place this string in the log file.
-fast
@@ -639,23 +712,37 @@ are specified, all parts of design will be removed.
finishing. produces smaller and more useful testcases, but may fail to
produce any testcase at all if the crash is related to dangling wires.
+It is possible to constrain which parts of the design will be considered for
+removal. Unless one or more of the following options are specified, all parts
+will be considered.
+
-modules
- try to remove modules.
+ try to remove modules. modules with a (* bugpoint_keep *) attribute
+ will be skipped.
-ports
- try to remove module ports.
+ try to remove module ports. ports with a (* bugpoint_keep *) attribute
+ will be skipped (useful for clocks, resets, etc.)
-cells
- try to remove cells.
+ try to remove cells. cells with a (* bugpoint_keep *) attribute will
+ be skipped.
-connections
try to reconnect ports to 'x.
+ -processes
+ try to remove processes. processes with a (* bugpoint_keep *) attribute
+ will be skipped.
+
-assigns
try to remove process assigns from cases.
-updates
try to remove process updates from syncs.
+
+ -runner "<prefix>"
+ child process wrapping command, e.g., "timeout 30", or valgrind.
\end{lstlisting}
\section{cd -- a shortcut for 'select -module <name>'}
@@ -690,30 +777,28 @@ This is just a shortcut for 'select -clear'.
This pass identifies the following problems in the current design:
- - combinatorial loops
-
- - two or more conflicting drivers for one wire
-
- - used wires that do not have a driver
+ - combinatorial loops
+ - two or more conflicting drivers for one wire
+ - used wires that do not have a driver
Options:
- -noinit
- Also check for wires which have the 'init' attribute set.
+ -noinit
+ also check for wires which have the 'init' attribute set
- -initdrv
- Also check for wires that have the 'init' attribute set and are not
- driven by an FF cell type.
+ -initdrv
+ also check for wires that have the 'init' attribute set and are not
+ driven by an FF cell type
- -mapped
- Also check for internal cells that have not been mapped to cells of the
- target architecture.
+ -mapped
+ also check for internal cells that have not been mapped to cells of the
+ target architecture
- -allow-tbuf
- Modify the -mapped behavior to still allow $_TBUF_ cells.
+ -allow-tbuf
+ modify the -mapped behavior to still allow $_TBUF_ cells
- -assert
- Produce a runtime error if any problems are found in the current design.
+ -assert
+ produce a runtime error if any problems are found in the current design
\end{lstlisting}
\section{chformal -- change formal constraints of the design}
@@ -794,6 +879,16 @@ When commands are separated using the ';;;' token, this command will be executed
in -purge mode between the commands.
\end{lstlisting}
+\section{clean\_zerowidth -- clean zero-width connections from the design}
+\label{cmd:clean_zerowidth}
+\begin{lstlisting}[numbers=left,frame=single]
+ clean_zerowidth [selection]
+
+Fixes the selected cells and processes to contain no zero-width connections.
+Depending on the cell type, this may be implemented by removing the connection,
+widening it to 1-bit, or removing the cell altogether.
+\end{lstlisting}
+
\section{clk2fflogic -- convert clocked FFs to generic \$ff cells}
\label{cmd:clk2fflogic}
\begin{lstlisting}[numbers=left,frame=single]
@@ -804,30 +899,32 @@ implicit global clock. This is useful for formal verification of designs with
multiple clocks.
\end{lstlisting}
-\section{clkbufmap -- insert global buffers on clock networks}
+\section{clkbufmap -- insert clock buffers on clock networks}
\label{cmd:clkbufmap}
\begin{lstlisting}[numbers=left,frame=single]
clkbufmap [options] [selection]
-Inserts global buffers between nets connected to clock inputs and their drivers.
+Inserts clock buffers between nets connected to clock inputs and their drivers.
In the absence of any selection, all wires without the 'clkbuf_inhibit'
-attribute will be considered for global buffer insertion.
+attribute will be considered for clock buffer insertion.
Alternatively, to consider all wires without the 'buffer_type' attribute set to
'none' or 'bufr' one would specify:
'w:* a:buffer_type=none a:buffer_type=bufr %u %d'
as the selection.
-buf <celltype> <portname_out>:<portname_in>
- Specifies the cell type to use for the global buffers
+ Specifies the cell type to use for the clock buffers
and its port names. The first port will be connected to
the clock network sinks, and the second will be connected
- to the actual clock source. This option is required.
+ to the actual clock source.
-inpad <celltype> <portname_out>:<portname_in>
If specified, a PAD cell of the given type is inserted on
clock nets that are also top module's inputs (in addition
- to the global buffer).
+ to the clock buffer, if any).
+
+At least one of -buf or -inpad should be specified.
\end{lstlisting}
\section{connect -- create or remove connections}
@@ -846,7 +943,7 @@ the -nounset option.
Unconnect all existing drivers for the specified expression.
- connect [-nomap] -port <cell> <port> <expr>
+ connect [-nomap] [-assert] -port <cell> <port> <expr>
Connect the specified cell port to the specified cell port.
@@ -858,6 +955,9 @@ this behavior.
The connect command operates in one module only. Either only one module must
be selected or an active module must be set using the 'cd' command.
+The -assert option verifies that the connection already exists, instead of
+making it.
+
This command does not operate on module with processes.
\end{lstlisting}
@@ -892,7 +992,7 @@ of JSON. Frontend responds with data or error message by replying with exactly
-> {"method": "derive", "module": "<module-name">, "parameters": {
"<param-name>": {"type": "[unsigned|signed|string|real]",
"value": "<param-value>"}, ...}}
- <- {"frontend": "[ilang|verilog|...]","source": "<source>"}}
+ <- {"frontend": "[rtlil|verilog|...]","source": "<source>"}}
<- {"error": "<error-message>"}
request for the module <module-name> to be derived for a specific set of
parameters. <param-name> starts with \ for named parameters, and with $
@@ -1041,6 +1141,14 @@ selected wires, thus 'deleting' module ports.
"Demote" inout ports to input or output ports, if possible.
\end{lstlisting}
+\section{demuxmap -- transform \$demux cells to \$eq + \$mux cells}
+\label{cmd:demuxmap}
+\begin{lstlisting}[numbers=left,frame=single]
+ demuxmap [selection]
+
+This pass transforms $demux cells to a bunch of equality comparisons.
+\end{lstlisting}
+
\section{design -- save, restore and reset current design}
\label{cmd:design}
\begin{lstlisting}[numbers=left,frame=single]
@@ -1102,61 +1210,10 @@ module that is then used as top module for this command.
The Verilog front-end remembers defined macros and top-level declarations
between calls to 'read_verilog'. This command resets this memory.
-\end{lstlisting}
-\section{determine\_init -- Determine the init value of cells}
-\label{cmd:determine_init}
-\begin{lstlisting}[numbers=left,frame=single]
- determine_init [selection]
+ design -delete <name>
-Determine the init value of cells that doesn't allow unknown init value.
-\end{lstlisting}
-
-\section{dff2dffe -- transform \$dff cells to \$dffe cells}
-\label{cmd:dff2dffe}
-\begin{lstlisting}[numbers=left,frame=single]
- dff2dffe [options] [selection]
-
-This pass transforms $dff cells driven by a tree of multiplexers with one or
-more feedback paths to $dffe cells. It also works on gate-level cells such as
-$_DFF_P_, $_DFF_N_ and $_MUX_.
-
- -unmap
- operate in the opposite direction: replace $dffe cells with combinations
- of $dff and $mux cells. the options below are ignored in unmap mode.
-
- -unmap-mince N
- Same as -unmap but only unmap $dffe where the clock enable port
- signal is used by less $dffe than the specified number
-
- -direct <internal_gate_type> <external_gate_type>
- map directly to external gate type. <internal_gate_type> can
- be any internal gate-level FF cell (except $_DFFE_??_). the
- <external_gate_type> is the cell type name for a cell with an
- identical interface to the <internal_gate_type>, except it
- also has an high-active enable port 'E'.
- Usually <external_gate_type> is an intermediate cell type
- that is then translated to the final type using 'techmap'.
-
- -direct-match <pattern>
- like -direct for all DFF cell types matching the expression.
- this will use $__DFFE_* as <external_gate_type> matching the
- internal gate type $_DFF_*_, and $__DFFSE_* for those matching
- $_DFFS_*_, except for $_DFF_[NP]_, which is converted to
- $_DFFE_[NP]_.
-\end{lstlisting}
-
-\section{dff2dffs -- process sync set/reset with SR over CE priority}
-\label{cmd:dff2dffs}
-\begin{lstlisting}[numbers=left,frame=single]
- dff2dffs [options] [selection]
-
-Merge synchronous set/reset $_MUX_ cells to create $__DFFS_[NP][NP][01], to be run before
-dff2dffe for SR over CE priority.
-
- -match-init
- Disallow merging synchronous set/reset that has polarity opposite of the
- output wire's init attribute (if any).
+Delete the design previously saved under the given name.
\end{lstlisting}
\section{dffinit -- set INIT param on FF cells}
@@ -1187,10 +1244,76 @@ drives. (This is primarily used in FPGA flows.)
the already defined initial value.
\end{lstlisting}
+\section{dfflegalize -- convert FFs to types supported by the target}
+\label{cmd:dfflegalize}
+\begin{lstlisting}[numbers=left,frame=single]
+ dfflegalize [options] [selection]
+
+Converts FFs to types supported by the target.
+
+ -cell <cell_type_pattern> <init_values>
+ specifies a supported group of FF cells. <cell_type_pattern>
+ is a yosys internal fine cell name, where ? characters can be
+ as a wildcard matching any character. <init_values> specifies
+ which initialization values these FF cells can support, and can
+ be one of:
+
+ - x (no init value supported)
+ - 0
+ - 1
+ - r (init value has to match reset value, only for some FF types)
+ - 01 (both 0 and 1 supported).
+
+ -mince <num>
+ specifies a minimum number of FFs that should be using any given
+ clock enable signal. If a clock enable signal doesn't meet this
+ threshold, it is unmapped into soft logic.
+
+ -minsrst <num>
+ specifies a minimum number of FFs that should be using any given
+ sync set/reset signal. If a sync set/reset signal doesn't meet this
+ threshold, it is unmapped into soft logic.
+
+The following cells are supported by this pass (ie. will be ingested,
+and can be specified as allowed targets):
+
+- $_DFF_[NP]_
+- $_DFFE_[NP][NP]_
+- $_DFF_[NP][NP][01]_
+- $_DFFE_[NP][NP][01][NP]_
+- $_ALDFF_[NP][NP]_
+- $_ALDFFE_[NP][NP][NP]_
+- $_DFFSR_[NP][NP][NP]_
+- $_DFFSRE_[NP][NP][NP][NP]_
+- $_SDFF_[NP][NP][01]_
+- $_SDFFE_[NP][NP][01][NP]_
+- $_SDFFCE_[NP][NP][01][NP]_
+- $_SR_[NP][NP]_
+- $_DLATCH_[NP]_
+- $_DLATCH_[NP][NP][01]_
+- $_DLATCHSR_[NP][NP][NP]_
+
+The following transformations are performed by this pass:
+- upconversion from a less capable cell to a more capable cell, if the less capable cell is not supported (eg. dff -> dffe, or adff -> dffsr)
+- unmapping FFs with clock enable (due to unsupported cell type or -mince)
+- unmapping FFs with sync reset (due to unsupported cell type or -minsrst)
+- adding inverters on the control pins (due to unsupported polarity)
+- adding inverters on the D and Q pins and inverting the init/reset values
+ (due to unsupported init or reset value)
+- converting sr into adlatch (by tying D to 1 and using E as set input)
+- emulating unsupported dffsr cell by adff + adff + sr + mux
+- emulating unsupported dlatchsr cell by adlatch + adlatch + sr + mux
+- emulating adff when the (reset, init) value combination is unsupported by
+ dff + adff + dlatch + mux
+- emulating adlatch when the (reset, init) value combination is unsupported by
+- dlatch + adlatch + dlatch + mux
+If the pass is unable to realize a given cell type (eg. adff when only plain dffis available), an error is raised.
+\end{lstlisting}
+
\section{dfflibmap -- technology mapping of flip-flops}
\label{cmd:dfflibmap}
\begin{lstlisting}[numbers=left,frame=single]
- dfflibmap [-prepare] -liberty <file> [selection]
+ dfflibmap [-prepare] [-map-only] [-info] -liberty <file> [selection]
Map internal flip-flop cells to the flip-flop cells in the technology
library specified in the given liberty file.
@@ -1200,16 +1323,40 @@ first run this pass and then map the logic paths to the target technology.
When called with -prepare, this command will convert the internal FF cells
to the internal cell types that best match the cells found in the given
-liberty file.
+liberty file, but won't actually map them to the target cells.
+
+When called with -map-only, this command will only map internal cell
+types that are already of exactly the right type to match the target
+cells, leaving remaining internal cells untouched.
+
+When called with -info, this command will only print the target cell
+list, along with their associated internal cell types, and the argumentsthat would be passed to the dfflegalize pass. The design will not be
+changed.
\end{lstlisting}
-\section{dump -- print parts of the design in ilang format}
+\section{dffunmap -- unmap clock enable and synchronous reset from FFs}
+\label{cmd:dffunmap}
+\begin{lstlisting}[numbers=left,frame=single]
+ dffunmap [options] [selection]
+
+This pass transforms FF types with clock enable and/or synchronous reset into
+their base type (with neither clock enable nor sync reset) by emulating the clock
+enable and synchronous reset with multiplexers on the cell input.
+
+ -ce-only
+ unmap only clock enables, leave synchronous resets alone.
+
+ -srst-only
+ unmap only synchronous resets, leave clock enables alone.
+\end{lstlisting}
+
+\section{dump -- print parts of the design in RTLIL format}
\label{cmd:dump}
\begin{lstlisting}[numbers=left,frame=single]
dump [options] [selection]
Write the selected parts of the design to the console or specified file in
-ilang format.
+RTLIL format.
-m
also dump the module headers, even if only parts of a single
@@ -1238,16 +1385,6 @@ Print all commands to log before executing them.
Do not print all commands to log before executing them. (default)
\end{lstlisting}
-\section{ecp5\_ffinit -- ECP5: handle FF init values}
-\label{cmd:ecp5_ffinit}
-\begin{lstlisting}[numbers=left,frame=single]
- ecp5_ffinit [options] [selection]
-
-Remove init values for FF output signals when equal to reset value.
-If reset is not used, set the reset value to the init value, otherwise
-unmap out the reset (if not an async reset).
-\end{lstlisting}
-
\section{ecp5\_gsr -- ECP5: handle GSR}
\label{cmd:ecp5_gsr}
\begin{lstlisting}[numbers=left,frame=single]
@@ -1278,14 +1415,6 @@ is a 4-tuple of source and sink cell type and port name.
Add Efinix adders to fix carry chain if needed.
\end{lstlisting}
-\section{efinix\_gbuf -- Efinix: insert global clock buffers}
-\label{cmd:efinix_gbuf}
-\begin{lstlisting}[numbers=left,frame=single]
- efinix_gbuf [options] [selection]
-
-Add Efinix global clock buffers to top module as needed.
-\end{lstlisting}
-
\section{equiv\_add -- add a \$equiv cell}
\label{cmd:equiv_add}
\begin{lstlisting}[numbers=left,frame=single]
@@ -1629,7 +1758,7 @@ outputs.
This pass looks for subcircuits that are isomorphic to any of the modules
in the given map file and replaces them with instances of this modules. The
-map file can be a Verilog source file (*.v) or an ilang file (*.il).
+map file can be a Verilog source file (*.v) or an RTLIL source file (*.il).
-map <map_file>
use the modules in this file as reference. This option can be used
@@ -1684,7 +1813,7 @@ This pass can also be used for mining for frequent subcircuits. In this mode
the following options are to be used instead of the -map option.
-mine <out_file>
- mine for frequent subcircuits and write them to the given ilang file
+ mine for frequent subcircuits and write them to the given RTLIL file
-mine_cells_span <min> <max>
only mine for subcircuits with the specified number of cells
@@ -2121,9 +2250,9 @@ Merge GP_INV cells with GP_DFF* and GP_DLATCH* cells.
In parametric designs, a module might exists in several variations with
different parameter values. This pass looks at all modules in the current
-design an re-runs the language frontends for the parametric modules as
+design and re-runs the language frontends for the parametric modules as
needed. It also resolves assignments to wired logic data types (wand/wor),
-resolves positional module parameters, unroll array instances, and more.
+resolves positional module parameters, unrolls array instances, and more.
-check
also check the design hierarchy. this generates an error when
@@ -2249,23 +2378,6 @@ input will be folded into the DSP. In this scenario only, resetting the
the accumulator to an arbitrary value can be inferred to use the {C,D} input.
\end{lstlisting}
-\section{ice40\_ffinit -- iCE40: handle FF init values}
-\label{cmd:ice40_ffinit}
-\begin{lstlisting}[numbers=left,frame=single]
- ice40_ffinit [options] [selection]
-
-Remove zero init values for FF output signals. Add inverters to implement
-nonzero init values.
-\end{lstlisting}
-
-\section{ice40\_ffssr -- iCE40: merge synchronous set/reset into FF cells}
-\label{cmd:ice40_ffssr}
-\begin{lstlisting}[numbers=left,frame=single]
- ice40_ffssr [options] [selection]
-
-Merge synchronous set/reset $_MUX_ cells into iCE40 FFs.
-\end{lstlisting}
-
\section{ice40\_opt -- iCE40: perform simple optimizations}
\label{cmd:ice40_opt}
\begin{lstlisting}[numbers=left,frame=single]
@@ -2277,7 +2389,7 @@ This command executes the following script:
<ice40 specific optimizations>
opt_expr -mux_undef -undriven [-full]
opt_merge
- opt_rmdff
+ opt_dff
opt_clean
while <changed design>
\end{lstlisting}
@@ -2321,26 +2433,28 @@ Map module inputs/outputs to PAD cells from a library. This pass
can only map to very simple PAD cells. Use 'techmap' to further map
the resulting cells to more sophisticated PAD cells.
- -inpad <celltype> <portname>[:<portname>]
+ -inpad <celltype> <in_port>[:<ext_port>]
Map module input ports to the given cell type with the
given output port name. if a 2nd portname is given, the
- signal is passed through the pad call, using the 2nd
+ signal is passed through the pad cell, using the 2nd
portname as the port facing the module port.
- -outpad <celltype> <portname>[:<portname>]
- -inoutpad <celltype> <portname>[:<portname>]
+ -outpad <celltype> <out_port>[:<ext_port>]
+ -inoutpad <celltype> <io_port>[:<ext_port>]
Similar to -inpad, but for output and inout ports.
- -toutpad <celltype> <portname>:<portname>[:<portname>]
+ -toutpad <celltype> <oe_port>:<out_port>[:<ext_port>]
Merges $_TBUF_ cells into the output pad cell. This takes precedence
over the other -outpad cell. The first portname is the enable input
- of the tristate driver.
+ of the tristate driver, which can be prefixed with `~` for negative
+ polarity enable.
- -tinoutpad <celltype> <portname>:<portname>:<portname>[:<portname>]
+ -tinoutpad <celltype> <oe_port>:<in_port>:<out_port>[:<ext_port>]
Merges $_TBUF_ cells into the inout pad cell. This takes precedence
over the other -inoutpad cell. The first portname is the enable input
of the tristate driver and the 2nd portname is the internal output
- buffering the external signal.
+ buffering the external signal. Like with `-toutpad`, the enable can
+ be marked as negative polarity by prefixing the name with `~`.
-ignore <celltype> <portname>[:<portname>]*
Skips mapping inputs/outputs that are already connected to given
@@ -2437,10 +2551,16 @@ options.
do not print warnings for the specified experimental feature
-expect <type> <regex> <expected_count>
- expect log,warning or error to appear. In case of error return code is 0.
+ expect log, warning or error to appear. matched errors will terminate
+ with exit code 0.
-expect-no-warnings
gives error in case there is at least one warning that is not expected.
+
+ -check-expected
+ verifies that the patterns previously set up by -expect have actually
+ been met, then clears the expected log list. If this is not called
+ manually, the check will happen at yosys exist time instead.
\end{lstlisting}
\section{ls -- list modules or objects in modules}
@@ -2485,16 +2605,19 @@ is used then the $macc cell is mapped to $add, $sub, etc. cells instead.
\section{memory -- translate memories to basic cells}
\label{cmd:memory}
\begin{lstlisting}[numbers=left,frame=single]
- memory [-nomap] [-nordff] [-memx] [-bram <bram_rules>] [selection]
+ memory [-nomap] [-nordff] [-nowiden] [-nosat] [-memx] [-bram <bram_rules>] [selection]
This pass calls all the other memory_* passes in a useful order:
opt_mem
- memory_dff [-nordff] (-memx implies -nordff)
- opt_clean
- memory_share
+ opt_mem_priority
+ opt_mem_feedback
+ memory_dff (skipped if called with -nordff or -memx)
opt_clean
+ memory_share [-nowiden] [-nosat]
+ opt_mem_widen
memory_memx (when called with -memx)
+ opt_clean
memory_collect
memory_bram -rules <bram_rules> (when called with -bram)
memory_map (skipped if called with -nomap)
@@ -2613,17 +2736,14 @@ This pass collects memories and memory ports and creates generic multiport
memory cells.
\end{lstlisting}
-\section{memory\_dff -- merge input/output DFFs into memories}
+\section{memory\_dff -- merge input/output DFFs into memory read ports}
\label{cmd:memory_dff}
\begin{lstlisting}[numbers=left,frame=single]
memory_dff [options] [selection]
-This pass detects DFFs at memory ports and merges them into the memory port.
+This pass detects DFFs at memory read ports and merges them into the memory port.
I.e. it consumes an asynchronous memory port and the flip-flops at its
interface and yields a synchronous memory port.
-
- -nordfff
- do not merge registers on read ports
\end{lstlisting}
\section{memory\_map -- translate multiport memories to basic cells}
@@ -2656,34 +2776,42 @@ This pass adds additional circuitry that emulates the Verilog simulation
behavior for out-of-bounds memory reads and writes.
\end{lstlisting}
+\section{memory\_narrow -- split up wide memory ports}
+\label{cmd:memory_narrow}
+\begin{lstlisting}[numbers=left,frame=single]
+ memory_narrow [options] [selection]
+
+This pass splits up wide memory ports into several narrow ports.
+\end{lstlisting}
+
\section{memory\_nordff -- extract read port FFs from memories}
\label{cmd:memory_nordff}
\begin{lstlisting}[numbers=left,frame=single]
memory_nordff [options] [selection]
This pass extracts FFs from memory read ports. This results in a netlist
-similar to what one would get from calling memory_dff with -nordff.
+similar to what one would get from not calling memory_dff.
\end{lstlisting}
\section{memory\_share -- consolidate memory ports}
\label{cmd:memory_share}
\begin{lstlisting}[numbers=left,frame=single]
- memory_share [selection]
+ memory_share [-nosat] [-nowiden] [selection]
This pass merges share-able memory ports into single memory ports.
The following methods are used to consolidate the number of memory ports:
- - When write ports are connected to async read ports accessing the same
- address, then this feedback path is converted to a write port with
- byte/part enable signals.
-
- When multiple write ports access the same address then this is converted
to a single write port with a more complex data and/or enable logic path.
+ - When multiple read or write ports access adjacent aligned addresses, they are
+ merged to a single wide read or write port. This transformation can be
+ disabled with the "-nowiden" option.
+
- When multiple write ports are never accessed at the same time (a SAT
solver is used to determine this), then the ports are merged into a single
- write port.
+ write port. This transformation can be disabled with the "-nosat" option.
Note that in addition to the algorithms implemented in this pass, the $memrd
and $memwr cells are also subject to generic resource sharing passes (and other
@@ -2890,27 +3018,27 @@ This pass calls all the other opt_* passes in a useful order. This performs
a series of trivial optimizations and cleanups. This pass executes the other
passes in the following order:
- opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]
+ opt_expr [-mux_undef] [-mux_bool] [-undriven] [-noclkinv] [-fine] [-full] [-keepdc]
opt_merge [-share_all] -nomux
do
opt_muxtree
opt_reduce [-fine] [-full]
opt_merge [-share_all]
- opt_share (-full only)
- opt_rmdff [-keepdc] [-sat]
+ opt_share (-full only)
+ opt_dff [-nodffe] [-nosdff] [-keepdc] [-sat] (except when called with -noff)
opt_clean [-purge]
- opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]
+ opt_expr [-mux_undef] [-mux_bool] [-undriven] [-noclkinv] [-fine] [-full] [-keepdc]
while <changed design>
When called with -fast the following script is used instead:
do
- opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]
+ opt_expr [-mux_undef] [-mux_bool] [-undriven] [-noclkinv] [-fine] [-full] [-keepdc]
opt_merge [-share_all]
- opt_rmdff [-keepdc] [-sat]
+ opt_dff [-nodffe] [-nosdff] [-keepdc] [-sat] (except when called with -noff)
opt_clean [-purge]
- while <changed design in opt_rmdff>
+ while <changed design in opt_dff>
Note: Options in square brackets (such as [-keepdc]) are passed through to
the opt_* commands when given to 'opt'.
@@ -2941,6 +3069,35 @@ This pass pushes inverters through $reduce_* cells if this will reduce the
overall gate count of the circuit
\end{lstlisting}
+\section{opt\_dff -- perform DFF optimizations}
+\label{cmd:opt_dff}
+\begin{lstlisting}[numbers=left,frame=single]
+ opt_dff [-nodffe] [-nosdff] [-keepdc] [-sat] [selection]
+
+This pass converts flip-flops to a more suitable type by merging clock enables
+and synchronous reset multiplexers, removing unused control inputs, or potentially
+removes the flip-flop altogether, converting it to a constant driver.
+
+ -nodffe
+ disables dff -> dffe conversion, and other transforms recognizing clock enable
+
+ -nosdff
+ disables dff -> sdff conversion, and other transforms recognizing sync resets
+
+ -simple-dffe
+ only enables clock enable recognition transform for obvious cases
+
+ -sat
+ additionally invoke SAT solver to detect and remove flip-flops (with
+ non-constant inputs) that can also be replaced with a constant driver
+
+ -keepdc
+ some optimizations change the behavior of the circuit with respect to
+ don't-care bits. for example in 'a+0' a single x-bit in 'a' will cause
+ all result bits to be set to x. this behavior changes when 'a+0' is
+ replaced by 'a'. the -keepdc option disables all such optimizations.
+\end{lstlisting}
+
\section{opt\_expr -- perform const folding and simple expression rewriting}
\label{cmd:opt_expr}
\begin{lstlisting}[numbers=left,frame=single]
@@ -2958,8 +3115,8 @@ It also performs some simple expression rewriting.
-undriven
replace undriven nets with undef (x) constants
- -clkinv
- optimize clock inverters by changing FF types
+ -noclkinv
+ do not optimize clock inverters by changing FF types
-fine
perform fine-grain optimizations
@@ -3015,6 +3172,38 @@ full set of inputs) or optimizations such as xilinx_dffopt.
This pass performs various optimizations on memories in the design.
\end{lstlisting}
+\section{opt\_mem\_feedback -- convert memory read-to-write port feedback paths to write enables}
+\label{cmd:opt_mem_feedback}
+\begin{lstlisting}[numbers=left,frame=single]
+ opt_mem_feedback [selection]
+
+This pass detects cases where an asynchronous read port is only connected via
+a mux tree to a write port with the same address. When such a connection is
+found, it is replaced with a new condition on an enable signal, allowing
+for removal of the read port.
+\end{lstlisting}
+
+\section{opt\_mem\_priority -- remove priority relations between write ports that can never collide}
+\label{cmd:opt_mem_priority}
+\begin{lstlisting}[numbers=left,frame=single]
+ opt_mem_priority [selection]
+
+This pass detects cases where one memory write port has priority over another
+even though they can never collide with each other -- ie. there can never be
+a situation where a given memory bit is written by both ports at the same
+time, for example because of always-different addresses, or mutually exclusive
+enable signals. In such cases, the priority relation is removed.
+\end{lstlisting}
+
+\section{opt\_mem\_widen -- optimize memories where all ports are wide}
+\label{cmd:opt_mem_widen}
+\begin{lstlisting}[numbers=left,frame=single]
+ opt_mem_widen [options] [selection]
+
+This pass looks for memories where all ports are wide and adjusts the base
+memory width up until that stops being the case.
+\end{lstlisting}
+
\section{opt\_merge -- consolidate identical cells}
\label{cmd:opt_merge}
\begin{lstlisting}[numbers=left,frame=single]
@@ -3062,19 +3251,6 @@ input with the original control signals OR'ed together.
alias for -fine
\end{lstlisting}
-\section{opt\_rmdff -- remove DFFs with constant inputs}
-\label{cmd:opt_rmdff}
-\begin{lstlisting}[numbers=left,frame=single]
- opt_rmdff [-keepdc] [-sat] [selection]
-
-This pass identifies flip-flops with constant inputs and replaces them with
-a constant driver.
-
- -sat
- additionally invoke SAT solver to detect and remove flip-flops (with
- non-constant inputs) that can also be replaced with a constant driver
-\end{lstlisting}
-
\section{opt\_share -- merge mutually exclusive cells of the same type that share an input signal}
\label{cmd:opt_share}
\begin{lstlisting}[numbers=left,frame=single]
@@ -3221,7 +3397,7 @@ on partly selected designs.
do not run any of the memory_* passes
-rdff
- do not pass -nordff to 'memory_dff'. This enables merging of FFs into
+ call 'memory_dff'. This enables merging of FFs into
memory read ports.
-nokeepdc
@@ -3244,19 +3420,27 @@ The following commands are executed by this synthesis command:
opt_expr -keepdc
opt_clean
check
- opt -keepdc
+ opt -noff -keepdc
wreduce -keepdc [-memx]
- memory_dff [-nordff]
+ memory_dff (if -rdff)
memory_memx (if -memx)
opt_clean
memory_collect
- opt -keepdc -fast
+ opt -noff -keepdc -fast
check:
stat
check
\end{lstlisting}
+\section{printattrs -- print attributes of selected objects}
+\label{cmd:printattrs}
+\begin{lstlisting}[numbers=left,frame=single]
+ printattrs [selection]
+
+Print all attributes of the selected objects.
+\end{lstlisting}
+
\section{proc -- translate processes to netlists}
\label{cmd:proc}
\begin{lstlisting}[numbers=left,frame=single]
@@ -3272,19 +3456,27 @@ This pass calls all the other proc_* passes in the most common order.
proc_mux
proc_dlatch
proc_dff
+ proc_memwr
proc_clean
+ opt_expr -keepdc
This replaces the processes in the design with multiplexers,
flip-flops and latches.
The following options are supported:
+ -nomux
+ Will omit the proc_mux pass.
+
-global_arst [!]<netname>
This option is passed through to proc_arst.
-ifx
This option is passed through to proc_mux. proc_rmdead is not
executed in -ifx mode.
+
+ -noopt
+ Will omit the opt_expr pass.
\end{lstlisting}
\section{proc\_arst -- detect asynchronous resets}
@@ -3344,6 +3536,14 @@ This pass extracts the 'init' actions from processes (generated from Verilog
respective wire.
\end{lstlisting}
+\section{proc\_memwr -- extract memory writes from processes}
+\label{cmd:proc_memwr}
+\begin{lstlisting}[numbers=left,frame=single]
+ proc_memwr [selection]
+
+This pass converts memory writes in processes into $memwr cells.
+\end{lstlisting}
+
\section{proc\_mux -- convert decision trees to multiplexers}
\label{cmd:proc_mux}
\begin{lstlisting}[numbers=left,frame=single]
@@ -3374,6 +3574,78 @@ a later assignment to the same signal and removes them.
This pass identifies unreachable branches in decision trees and removes them.
\end{lstlisting}
+\section{qbfsat -- solve a 2QBF-SAT problem in the circuit}
+\label{cmd:qbfsat}
+\begin{lstlisting}[numbers=left,frame=single]
+ qbfsat [options] [selection]
+
+This command solves an "exists-forall" 2QBF-SAT problem defined over the currently
+selected module. Existentially-quantified variables are declared by assigning a wire
+"$anyconst". Universally-quantified variables may be explicitly declared by assigning
+a wire "$allconst", but module inputs will be treated as universally-quantified
+variables by default.
+
+ -nocleanup
+ Do not delete temporary files and directories. Useful for debugging.
+
+ -dump-final-smt2 <file>
+ Pass the --dump-smt2 option to yosys-smtbmc.
+
+ -assume-outputs
+ Add an "$assume" cell for the conjunction of all one-bit module output wires.
+
+ -assume-negative-polarity
+ When adding $assume cells for one-bit module output wires, assume they are
+ negative polarity signals and should always be low, for example like the
+ miters created with the `miter` command.
+
+ -nooptimize
+ Ignore "\minimize" and "\maximize" attributes, do not emit "(maximize)" or
+ "(minimize)" in the SMT-LIBv2, and generally make no attempt to optimize anything.
+
+ -nobisection
+ If a wire is marked with the "\minimize" or "\maximize" attribute, do not
+ attempt to optimize that value with the default iterated solving and threshold
+ bisection approach. Instead, have yosys-smtbmc emit a "(minimize)" or "(maximize)"
+ command in the SMT-LIBv2 output and hope that the solver supports optimizing
+ quantified bitvector problems.
+
+ -solver <solver>
+ Use a particular solver. Choose one of: "z3", "yices", and "cvc4".
+ (default: yices)
+
+ -solver-option <name> <value>
+ Set the specified solver option in the SMT-LIBv2 problem file.
+
+ -timeout <value>
+ Set the per-iteration timeout in seconds.
+ (default: no timeout)
+
+ -O0, -O1, -O2
+ Control the use of ABC to simplify the QBF-SAT problem before solving.
+
+ -sat
+ Generate an error if the solver does not return "sat".
+
+ -unsat
+ Generate an error if the solver does not return "unsat".
+
+ -show-smtbmc
+ Print the output from yosys-smtbmc.
+
+ -specialize
+ If the problem is satisfiable, replace each "$anyconst" cell with its
+ corresponding constant value from the model produced by the solver.
+
+ -specialize-from-file <solution file>
+ Do not run the solver, but instead only attempt to replace each "$anyconst"
+ cell in the current module with a constant value provided by the specified file.
+
+ -write-solution <solution file>
+ If the problem is satisfiable, write the corresponding constant value for each
+ "$anyconst" cell from the model produced by the solver to the specified file.
+\end{lstlisting}
+
\section{qwp -- quadratic wirelength placer}
\label{cmd:qwp}
\begin{lstlisting}[numbers=left,frame=single]
@@ -3420,6 +3692,12 @@ the language version (and before file names) to set additional verilog defines.
Load the specified VHDL files. (Requires Verific.)
+ read {-f|-F} <command-file>
+
+Load and execute the specified command file. (Requires Verific.)
+Check verific command for more information about supported commands in file.
+
+
read -define <macro>[=<value>]..
Set global Verilog/SystemVerilog defines.
@@ -3483,24 +3761,10 @@ Load modules from a BLIF file into the current design.
multi-bit port 'name'.
\end{lstlisting}
-\section{read\_ilang -- read modules from ilang file}
+\section{read\_ilang -- (deprecated) alias of read\_rtlil}
\label{cmd:read_ilang}
\begin{lstlisting}[numbers=left,frame=single]
- read_ilang [filename]
-
-Load modules from an ilang file to the current design. (ilang is a text
-representation of a design in yosys's internal format.)
-
- -nooverwrite
- ignore re-definitions of modules. (the default behavior is to
- create an error message if the existing module is not a blackbox
- module, and overwrite the existing module if it is a blackbox module.)
-
- -overwrite
- overwrite existing modules with the same name
-
- -lib
- only create empty blackbox modules
+See `help read_rtlil`.
\end{lstlisting}
\section{read\_json -- read JSON file}
@@ -3544,6 +3808,26 @@ Read cells from liberty file as modules into current design.
set the specified attribute (to the value 1) on all loaded modules
\end{lstlisting}
+\section{read\_rtlil -- read modules from RTLIL file}
+\label{cmd:read_rtlil}
+\begin{lstlisting}[numbers=left,frame=single]
+ read_rtlil [filename]
+
+Load modules from an RTLIL file to the current design. (RTLIL is a text
+representation of a design in yosys's internal format.)
+
+ -nooverwrite
+ ignore re-definitions of modules. (the default behavior is to
+ create an error message if the existing module is not a blackbox
+ module, and overwrite the existing module if it is a blackbox module.)
+
+ -overwrite
+ overwrite existing modules with the same name
+
+ -lib
+ only create empty blackbox modules
+\end{lstlisting}
+
\section{read\_verilog -- read modules from Verilog file}
\label{cmd:read_verilog}
\begin{lstlisting}[numbers=left,frame=single]
@@ -3560,6 +3844,9 @@ Verilog-2005 is supported.
enable support for SystemVerilog assertions and some Yosys extensions
replace the implicit -D SYNTHESIS with -D FORMAL
+ -nosynthesis
+ don't add implicit -D SYNTHESIS
+
-noassert
ignore assert() statements
@@ -3701,8 +3988,8 @@ recommended to use a simulator (for example Icarus Verilog) for checking
the syntax of the code, rather than to rely on read_verilog for that.
Depending on if read_verilog is run in -formal mode, either the macro
-SYNTHESIS or FORMAL is defined automatically. In addition, read_verilog
-always defines the macro YOSYS.
+SYNTHESIS or FORMAL is defined automatically, unless -nosynthesis is used.
+In addition, read_verilog always defines the macro YOSYS.
See the Yosys README file for a list of non-standard Verilog features
supported by the Yosys Verilog front-end.
@@ -3952,7 +4239,7 @@ This command identifies strongly connected components (aka logic loops) in the
design.
-expect <num>
- expect to find exactly <num> SSCs. A different number of SSCs will
+ expect to find exactly <num> SCCs. A different number of SCCs will
produce an error.
-max_depth <num>
@@ -3977,6 +4264,9 @@ design.
-select
replace the current selection with a selection of all cells and wires
that are part of a found logic loop
+
+ -specify
+ examine specify rules to detect logic loops in whitebox/blackbox cells
\end{lstlisting}
\section{scratchpad -- get/set values in the scratchpad}
@@ -4040,6 +4330,7 @@ in the scope of (and thus, relative to) the wires' owning module(s). This
\label{cmd:select}
\begin{lstlisting}[numbers=left,frame=single]
select [ -add | -del | -set <name> ] {-read <filename> | <selection>}
+ select [ -unset <name> ]
select [ <assert_option> ] {-read <filename> | <selection>}
select [ -list | -write <filename> | -count | -clear ]
select -module <modname>
@@ -4062,6 +4353,9 @@ described here.
under the given name (see @<name> below). to save the current selection,
use "select -set <name> %"
+ -unset <name>
+ do not modify the current selection. instead remove a previously saved
+ selection under the given name (see @<name> below).
-assert-none
do not modify the current selection. instead assert that the given
selection is empty. i.e. produce an error if any object matching the
@@ -4132,6 +4426,8 @@ Pushing (selecting) object when in -module mode:
<obj_pattern>
select the specified object(s) from the current module
+By default, patterns will not match black/white-box modules or theircontents. To include such objects, prefix the pattern with '='.
+
A <mod_pattern> can be a module name, wildcard expression (*, ?, [..])
matching module names, or one of the following:
@@ -4318,17 +4614,6 @@ This command replaces undef (x) constants with defined (0/1) constants.
replace undef in cell parameters
\end{lstlisting}
-\section{sf2\_iobs -- SF2: insert IO buffers}
-\label{cmd:sf2_iobs}
-\begin{lstlisting}[numbers=left,frame=single]
- sf2_iobs [options] [selection]
-
-Add SF2 I/O buffers and global buffers to top module as needed.
-
- -clkbuf
- Insert PAD->global_net clock buffers
-\end{lstlisting}
-
\section{share -- perform sat-based resource sharing}
\label{cmd:share}
\begin{lstlisting}[numbers=left,frame=single]
@@ -4410,7 +4695,7 @@ to a graphics file (usually SVG or PostScript).
generate a .dot file, or other <format> strings such as 'svg' or 'ps'
to generate files in other formats (this calls the 'dot' command).
- -lib <verilog_or_ilang_file>
+ -lib <verilog_or_rtlil_file>
Use the specified library file for determining whether cell ports are
inputs or outputs. This option can be used multiple times to specify
more than one library.
@@ -4453,7 +4738,7 @@ to a graphics file (usually SVG or PostScript).
(including inout ports) are on the right side.
-pause
- wait for the use to press enter to before returning
+ wait for the user to press enter to before returning
-enum
enumerate objects with internal ($-prefixed) names
@@ -4546,6 +4831,9 @@ This command simulates the circuit using the given top-level module.
-vcd <filename>
write the simulation results to the given VCD file
+ -fst <filename>
+ write the simulation results to the given FST file
+
-clock <portname>
name of top-level clock input
@@ -4564,15 +4852,45 @@ This command simulates the circuit using the given top-level module.
-zinit
zero-initialize all uninitialized regs and memories
+ -timescale <string>
+ include the specified timescale declaration in the vcd
+
-n <integer>
- number of cycles to simulate (default: 20)
+ number of clock cycles to simulate (default: 20)
-a
- include all nets in VCD output, not just those with public names
+ use all nets in VCD/FST operations, not just those with public names
-w
writeback mode: use final simulation state as new init state
+ -r
+ read simulation results file (file formats supported: FST)
+
+ -scope
+ scope of simulation top model
+
+ -at <time>
+ sets start and stop time
+
+ -start <time>
+ start co-simulation in arbitary time (default 0)
+
+ -stop <time>
+ stop co-simulation in arbitary time (default END)
+
+ -sim
+ simulation with stimulus from FST (default)
+
+ -sim-cmp
+ co-simulation expect exact match
+
+ -sim-gold
+ co-simulation, x in simulation can match any value in FST
+
+ -sim-gate
+ co-simulation, x in FST can match any value in simulation
+
-d
enable debug output
\end{lstlisting}
@@ -4588,7 +4906,7 @@ primitives. The following internal cell types are mapped by this pass:
$not, $pos, $and, $or, $xor, $xnor
$reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool
$logic_not, $logic_and, $logic_or, $mux, $tribuf
- $sr, $ff, $dff, $dffsr, $adff, $dlatch
+ $sr, $ff, $dff, $dffe, $dffsr, $dffsre, $adff, $adffe, $aldff, $aldffe, $sdff, $sdffe, $sdffce, $dlatch, $adlatch, $dlatchsr
\end{lstlisting}
\section{splice -- create explicit splicing cells}
@@ -4652,6 +4970,15 @@ This command splits multi-bit nets into single-bit nets.
and split nets so that no driver drives only part of a net.
\end{lstlisting}
+\section{sta -- perform static timing analysis}
+\label{cmd:sta}
+\begin{lstlisting}[numbers=left,frame=single]
+ sta [options] [selection]
+
+This command performs static timing analysis on the design. (Only considers
+paths within a single module, so the design must be flattened.)
+\end{lstlisting}
+
\section{stat -- print some statistics}
\label{cmd:stat}
\begin{lstlisting}[numbers=left,frame=single]
@@ -4780,6 +5107,8 @@ The following commands are executed by this synthesis command:
opt_expr
opt_clean
check
+ opt -nodffe -nosdff
+ fsm (unless -nofsm)
opt
wreduce
peepopt
@@ -4788,8 +5117,6 @@ The following commands are executed by this synthesis command:
alumacc (unless -noalumacc)
share (unless -noshare)
opt
- fsm (unless -nofsm)
- opt -fast
memory -nomap
opt_clean
@@ -4857,12 +5184,12 @@ The following commands are executed by this synthesis command:
opt -fast -mux_undef -undriven -fine -full
memory_map
opt -undriven -fine
- dff2dffe -direct-match $_DFF_*
opt -fine
techmap -map +/techmap.v
opt -full
clean -purge
setundef -undriven -zero
+ dfflegalize -cell $_DFF_P_ x
abc -markgroups -dff -D 1 (only if -retime)
map_luts:
@@ -4878,6 +5205,7 @@ The following commands are executed by this synthesis command:
hierarchy -check
stat
check -noinit
+ blackbox =A:whitebox
vout:
write_verilog -nodec -attr2comment -defparam -renameprefix syn_ <file-name>
@@ -4915,6 +5243,9 @@ This command runs synthesis for Anlogic FPGAs.
-nolutram
do not use EG_LOGIC_DRAM16X4 cells in output netlist
+ -nobram
+ do not use EG_PHY_BRAM or EG_PHY_BRAM32K cells in output netlist
+
The following commands are executed by this synthesis command:
@@ -4931,6 +5262,12 @@ The following commands are executed by this synthesis command:
coarse:
synth -run coarse
+ map_bram: (skip if -nobram)
+ memory_bram -rules +/anlogic/brams.txt
+ techmap -map +/anlogic/brams_map.v
+ setundef -zero -params t:EG_PHY_BRAM
+ setundef -zero -params t:EG_PHY_BRAM32K
+
map_lutram: (skip if -nolutram)
memory_bram -rules +/anlogic/lutrams.txt
techmap -map +/anlogic/lutrams_map.v
@@ -4947,8 +5284,8 @@ The following commands are executed by this synthesis command:
abc -dff -D 1 (only if -retime)
map_ffs:
+ dfflegalize -cell $_DFFE_P??P_ r -cell $_SDFFE_P??P_ r -cell $_DLATCH_N??_ r
techmap -D NO_LUT -map +/anlogic/cells_map.v
- dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit
opt_expr -mux_undef
simplemap
@@ -4968,6 +5305,7 @@ The following commands are executed by this synthesis command:
hierarchy -check
stat
check -noinit
+ blackbox =A:whitebox
edif:
write_edif <file-name>
@@ -5057,6 +5395,7 @@ The following commands are executed by this synthesis command:
hierarchy -check
stat
check -noinit
+ blackbox =A:whitebox
json:
write_json <file-name>
@@ -5123,6 +5462,7 @@ The following commands are executed by this synthesis command:
hierarchy -check
stat
check -noinit
+ blackbox =A:whitebox
vlog:
write_verilog -noexpr -attr2comment <file-name>
@@ -5158,6 +5498,9 @@ This command runs synthesis for ECP5 FPGAs.
-noflatten
do not flatten design before synthesis
+ -dff
+ run 'abc'/'abc9' with -dff option
+
-retime
run 'abc' with '-dff -D 1' options
@@ -5177,7 +5520,7 @@ This command runs synthesis for ECP5 FPGAs.
do not use PFU muxes to implement LUTs larger than LUT4s
-asyncprld
- use async PRLD mode to implement DLATCH and DFFSR (EXPERIMENTAL)
+ use async PRLD mode to implement ALDFF (EXPERIMENTAL)
-abc2
run two passes of 'abc' for slightly improved logic density
@@ -5207,6 +5550,8 @@ The following commands are executed by this synthesis command:
opt_expr
opt_clean
check
+ opt -nodffe -nosdff
+ fsm
opt
wreduce
peepopt
@@ -5219,8 +5564,6 @@ The following commands are executed by this synthesis command:
chtype -set $mul t:$__soft_mul (unless -nodsp)
alumacc
opt
- fsm
- opt -fast
memory -nomap
opt_clean
@@ -5243,25 +5586,24 @@ The following commands are executed by this synthesis command:
abc -dff -D 1 (only if -retime)
map_ffs:
- dff2dffs
opt_clean
- dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*
- techmap -D NO_LUT [-D ASYNC_PRLD] -map +/ecp5/cells_map.v
+ dfflegalize -cell $_DFF_?_ 01 -cell $_DFF_?P?_ r -cell $_SDFF_?P?_ r [-cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r] [-cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x] [-cell $_DLATCH_?_ x] ($_ALDFF_*_ only if -asyncprld, $_DLATCH_* only if not -asyncprld, $_*DFFE_* only if not -nodffe)
+ zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF* (only if -abc9 and -dff)
+ techmap -D NO_LUT -map +/ecp5/cells_map.v
opt_expr -undriven -mux_undef
simplemap
- ecp5_ffinit
ecp5_gsr
attrmvcp -copy -attr syn_useioff
opt_clean
map_luts:
abc (only if -abc2)
- techmap -map +/ecp5/latches_map.v
- abc -lut 4:7 -dress
+ techmap -map +/ecp5/latches_map.v (skip if -asyncprld)
+ abc -dress -lut 4:7
clean
map_cells:
- techmap -map +/ecp5/cells_map.v (with -D NO_LUT in vpr mode)
+ techmap -map +/ecp5/cells_map.v (skip if -vpr)
opt_lut_ins -tech ecp5
clean
@@ -5270,6 +5612,7 @@ The following commands are executed by this synthesis command:
hierarchy -check
stat
check -noinit
+ blackbox =A:whitebox
blif:
opt_clean -purge (vpr mode)
@@ -5345,8 +5688,8 @@ The following commands are executed by this synthesis command:
abc -dff -D 1 (only if -retime)
map_ffs:
+ dfflegalize -cell $_DFFE_????_ 0 -cell $_SDFFE_????_ 0 -cell $_SDFFCE_????_ 0 -cell $_DLATCH_?_ x
techmap -D NO_LUT -map +/efinix/cells_map.v
- dffinit -strinit SET RESET -ff AL_MAP_SEQ q REGSET -noreinit
opt_expr -mux_undef
simplemap
@@ -5359,7 +5702,8 @@ The following commands are executed by this synthesis command:
clean
map_gbuf:
- efinix_gbuf
+ clkbufmap -buf $__EFX_GBUF O:I
+ techmap -map +/efinix/gbuf_map.v
efinix_fixcarry
clean
@@ -5367,6 +5711,7 @@ The following commands are executed by this synthesis command:
hierarchy -check
stat
check -noinit
+ blackbox =A:whitebox
edif:
write_edif <file-name>
@@ -5375,6 +5720,149 @@ The following commands are executed by this synthesis command:
write_json <file-name>
\end{lstlisting}
+\section{synth\_gatemate -- synthesis for Cologne Chip GateMate FPGAs}
+\label{cmd:synth_gatemate}
+\begin{lstlisting}[numbers=left,frame=single]
+ synth_gatemate [options]
+
+This command runs synthesis for Cologne Chip AG GateMate FPGAs.
+
+ -top <module>
+ use the specified module as top module.
+
+ -vlog <file>
+ write the design to the specified verilog file. Writing of an output
+ file is omitted if this parameter is not specified.
+
+ -json <file>
+ write the design to the specified JSON file. Writing of an output file
+ is omitted if this parameter is not specified.
+
+ -run <from_label>:<to_label>
+ only run the commands between the labels (see below). An empty
+ from label is synonymous to 'begin', and empty to label is
+ synonymous to the end of the command list.
+
+ -noflatten
+ do not flatten design before synthesis.
+
+ -nobram
+ do not use CC_BRAM_20K or CC_BRAM_40K cells in output netlist.
+
+ -noaddf
+ do not use CC_ADDF full adder cells in output netlist.
+
+ -nomult
+ do not use CC_MULT multiplier cells in output netlist.
+
+ -nomx8, -nomx4
+ do not use CC_MX{8,4} multiplexer cells in output netlist.
+
+ -dff
+ run 'abc' with -dff option
+
+ -retime
+ run 'abc' with '-dff -D 1' options
+
+ -noiopad
+ disable I/O buffer insertion (useful for hierarchical or
+ out-of-context flows).
+
+ -noclkbuf
+ disable automatic clock buffer insertion.
+
+The following commands are executed by this synthesis command:
+
+ begin:
+ read_verilog -lib -specify +/gatemate/cells_sim.v +/gatemate/cells_bb.v
+ hierarchy -check -top <top>
+
+ prepare:
+ proc
+ flatten
+ tribuf -logic
+ deminout
+ opt_expr
+ opt_clean
+ check
+ opt -nodffe -nosdff
+ fsm
+ opt
+ wreduce
+ peepopt
+ opt_clean
+ muxpack
+ share
+ techmap -map +/cmp2lut.v -D LUT_WIDTH=4
+ opt_expr
+ opt_clean
+
+ map_mult: (skip if '-nomult')
+ techmap -map +/gatemate/mul_map.v
+
+ coarse:
+ alumacc
+ opt
+ memory -nomap
+ opt_clean
+
+ map_bram: (skip if '-nobram')
+ memory_bram -rules +/gatemate/brams.txt
+ setundef -zero -params t:$__CC_BRAM_CASCADE t:$__CC_BRAM_40K_SDP t:$__CC_BRAM_20K_SDP t:$__CC_BRAM_20K_TDP t:$__CC_BRAM_40K_TDP
+ techmap -map +/gatemate/brams_map.v
+
+ map_ffram:
+ opt -fast -mux_undef -undriven -fine
+ memory_map
+ opt -undriven -fine
+
+ map_gates:
+ techmap -map +/techmap.v -map +/gatemate/arith_map.v
+ opt -fast
+
+ map_io: (skip if '-noiopad')
+ iopadmap -bits -inpad CC_IBUF Y:I -outpad CC_OBUF A:O -toutpad CC_TOBUF ~T:A:O -tinoutpad CC_IOBUF ~T:Y:A:IO
+ clean
+
+ map_regs:
+ opt_clean
+ dfflegalize -cell $_DFFE_????_ x -cell $_DLATCH_???_ x
+ techmap -map +/gatemate/reg_map.v
+ opt_expr -mux_undef
+ simplemap
+ opt_clean
+
+ map_muxs:
+ muxcover -mux4 -mux8
+ opt -full
+ techmap -map +/gatemate/mux_map.v
+
+ map_luts:
+ abc -dress -lut 4
+ clean
+
+ map_cells:
+ techmap -map +/gatemate/lut_map.v
+ clean
+
+ map_bufg: (skip if '-noclkbuf')
+ clkbufmap -buf CC_BUFG O:I
+ clean
+
+ check:
+ hierarchy -check
+ stat -width
+ check -noinit
+ blackbox =A:whitebox
+
+ vlog:
+ opt_clean -purge
+ write_verilog -noattr <file-name>
+
+ json:
+ write_json <file-name>
+\end{lstlisting}
+
\section{synth\_gowin -- synthesis for Gowin FPGAs}
\label{cmd:synth_gowin}
\begin{lstlisting}[numbers=left,frame=single]
@@ -5389,6 +5877,11 @@ This command runs synthesis for Gowin FPGAs. This work is experimental.
write the design to the specified Verilog netlist file. writing of an
output file is omitted if this parameter is not specified.
+ -json <file>
+ write the design to the specified JSON netlist file. writing of an
+ output file is omitted if this parameter is not specified.
+ This disables features not yet supported by nexpnr-gowin.
+
-run <from_label>:<to_label>
only run the commands between the labels (see below). an empty
from label is synonymous to 'begin', and empty to label is
@@ -5415,11 +5908,17 @@ This command runs synthesis for Gowin FPGAs. This work is experimental.
-noiopads
do not emit IOB at top level ports
+ -noalu
+ do not use ALU cells
+
+ -abc9
+ use new ABC9 flow (EXPERIMENTAL)
+
The following commands are executed by this synthesis command:
begin:
- read_verilog -lib +/gowin/cells_sim.v
+ read_verilog -specify -lib +/gowin/cells_sim.v
hierarchy -check -top <top>
flatten: (unless -noflatten)
@@ -5438,7 +5937,7 @@ The following commands are executed by this synthesis command:
map_lutram: (skip if -nolutram)
memory_bram -rules +/gowin/lutrams.txt
techmap -map +/gowin/lutrams_map.v
- determine_init
+ setundef -params -zero t:RAM16S4
map_ffram:
opt -fast -mux_undef -undriven -fine
@@ -5449,12 +5948,11 @@ The following commands are executed by this synthesis command:
techmap -map +/techmap.v -map +/gowin/arith_map.v
opt -fast
abc -dff -D 1 (only if -retime)
- splitnets
+ iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O -toutpad TBUF ~OEN:I:O -tinoutpad IOBUF ~OEN:O:I:IO (unless -noiopads)
map_ffs:
- dff2dffs -match-init
opt_clean
- dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*
+ dfflegalize -cell $_DFF_?_ 0 -cell $_DFFE_?P_ 0 -cell $_SDFF_?P?_ r -cell $_SDFFE_?P?P_ r -cell $_DFF_?P?_ r -cell $_DFFE_?P?P_ r
techmap -map +/gowin/cells_map.v
opt_expr -mux_undef
simplemap
@@ -5468,16 +5966,19 @@ The following commands are executed by this synthesis command:
opt_lut_ins -tech gowin
setundef -undriven -params -zero
hilomap -singleton -hicell VCC V -locell GND G
- iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O -toutpad TBUF OEN:I:O -tinoutpad IOBUF OEN:O:I:IO (unless -noiopads)
+ splitnets -ports (only if -vout used)
clean
+ autoname
check:
hierarchy -check
stat
check -noinit
+ blackbox =A:whitebox
vout:
- write_verilog -decimal -attr2comment -defparam -renameprefix gen <file-name>
+ write_verilog -simple-lhs -decimal -attr2comment -defparam -renameprefix gen <file-name>
+ write_json <file-name>
\end{lstlisting}
\section{synth\_greenpak4 -- synthesis for GreenPAK4 FPGAs}
@@ -5534,7 +6035,7 @@ The following commands are executed by this synthesis command:
opt -undriven -fine
techmap -map +/techmap.v -map +/greenpak4/cells_latch.v
dfflibmap -prepare -liberty +/greenpak4/gp_dff.lib
- opt -fast
+ opt -fast -noclkinv -noff
abc -dff -D 1 (only if -retime)
map_luts:
@@ -5561,6 +6062,7 @@ The following commands are executed by this synthesis command:
hierarchy -check
stat
check -noinit
+ blackbox =A:whitebox
json:
write_json <file-name>
@@ -5600,6 +6102,9 @@ This command runs synthesis for iCE40 FPGAs.
-noflatten
do not flatten design before synthesis
+ -dff
+ run 'abc'/'abc9' with -dff option
+
-retime
run 'abc' with '-dff -D 1' options
@@ -5652,6 +6157,8 @@ The following commands are executed by this synthesis command:
opt_expr
opt_clean
check
+ opt -nodffe -nosdff
+ fsm
opt
wreduce
peepopt
@@ -5672,8 +6179,6 @@ The following commands are executed by this synthesis command:
chtype -set $mul t:$__soft_mul (if -dsp)
alumacc
opt
- fsm
- opt -fast
memory -nomap
opt_clean
@@ -5695,12 +6200,10 @@ The following commands are executed by this synthesis command:
ice40_opt
map_ffs:
- dff2dffe -direct-match $_DFF_*
- techmap -D NO_LUT -D NO_ADDER -map +/ice40/cells_map.v
+ dfflegalize -cell $_DFF_?_ 0 -cell $_DFFE_?P_ 0 -cell $_DFF_?P?_ 0 -cell $_DFFE_?P?P_ 0 -cell $_SDFF_?P?_ 0 -cell $_SDFFCE_?P?P_ 0 -cell $_DLATCH_?_ x -mince -1
+ techmap -map +/ice40/ff_map.v
opt_expr -mux_undef
simplemap
- ice40_ffinit
- ice40_ffssr
ice40_opt -full
map_luts:
@@ -5710,14 +6213,14 @@ The following commands are executed by this synthesis command:
simplemap (if -noabc or -flowmap)
techmap -map +/gate2lut.v -D LUT_WIDTH=4 (only if -noabc)
flowmap -maxlut 4 (only if -flowmap)
- abc -dress -lut 4 (skip if -noabc)
+ abc -dress -lut 4 (skip if -noabc)
ice40_wrapcarry -unwrap
- techmap -D NO_LUT -map +/ice40/cells_map.v
+ techmap -map +/ice40/ff_map.v
clean
- opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0
+ opt_lut -dlogic SB_CARRY:I0=1:I1=2:CI=3 -dlogic SB_CARRY:CO=3
map_cells:
- techmap -map +/ice40/cells_map.v (with -D NO_LUT in vpr mode)
+ techmap -map +/ice40/cells_map.v (skip if -vpr)
clean
check:
@@ -5725,6 +6228,7 @@ The following commands are executed by this synthesis command:
hierarchy -check
stat
check -noinit
+ blackbox =A:whitebox
blif:
opt_clean -purge (vpr mode)
@@ -5745,11 +6249,11 @@ The following commands are executed by this synthesis command:
This command runs synthesis for Intel FPGAs.
- -family <max10 | arria10gx | cyclone10lp | cyclonev | cycloneiv | cycloneive>
+ -family <max10 | cyclone10lp | cycloneiv | cycloneive>
generate the synthesis netlist for the specified family.
MAX10 is the default target if no family argument specified.
For Cyclone IV GX devices, use cycloneiv argument; for Cyclone IV E, use cycloneive.
- Cyclone V and Arria 10 GX devices are experimental.
+ For Cyclone V and Cyclone 10 GX, use the synth_intel_alm backend instead.
-top <module>
use the specified module as top module (default='top')
@@ -5809,14 +6313,16 @@ The following commands are executed by this synthesis command:
opt -fast -mux_undef -undriven -fine -full
memory_map
opt -undriven -fine
- dff2dffe -direct-match $_DFF_*
- opt -fine
techmap -map +/techmap.v
opt -full
clean -purge
setundef -undriven -zero
abc -markgroups -dff -D 1 (only if -retime)
+ map_ffs:
+ dfflegalize -cell $_DFFE_PN0P_ 01
+ techmap -map +/intel/common/ff_map.v
+
map_luts:
abc -lut 4
clean
@@ -5824,13 +6330,13 @@ The following commands are executed by this synthesis command:
map_cells:
iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I (if -iopads)
techmap -map +/intel/max10/cells_map.v
- dffinit -highlow -ff dffeas q power_up
clean -purge
check:
hierarchy -check
stat
check -noinit
+ blackbox =A:whitebox
vqm:
write_verilog -attr2comment -defparam -nohex -decimal -renameprefix syn_ <file-name>
@@ -5843,6 +6349,496 @@ The following commands are executed by this synthesis command:
WARNING: THE 'synth_intel' COMMAND IS EXPERIMENTAL.
\end{lstlisting}
+\section{synth\_intel\_alm -- synthesis for ALM-based Intel (Altera) FPGAs.}
+\label{cmd:synth_intel_alm}
+\begin{lstlisting}[numbers=left,frame=single]
+ synth_intel_alm [options]
+
+This command runs synthesis for ALM-based Intel FPGAs.
+
+ -top <module>
+ use the specified module as top module
+
+ -family <family>
+ target one of:
+ "cyclonev" - Cyclone V (default)
+ "arriav" - Arria V (non-GZ) "cyclone10gx" - Cyclone 10GX
+
+ -vqm <file>
+ write the design to the specified Verilog Quartus Mapping File. Writing of an
+ output file is omitted if this parameter is not specified. Implies -quartus.
+
+ -noflatten
+ do not flatten design before synthesis; useful for per-module area statistics
+
+ -quartus
+ output a netlist using Quartus cells instead of MISTRAL_* cells
+
+ -dff
+ pass DFFs to ABC to perform sequential logic optimisations (EXPERIMENTAL)
+
+ -run <from_label>:<to_label>
+ only run the commands between the labels (see below). an empty
+ from label is synonymous to 'begin', and empty to label is
+ synonymous to the end of the command list.
+
+ -nolutram
+ do not use LUT RAM cells in output netlist
+
+ -nobram
+ do not use block RAM cells in output netlist
+
+ -nodsp
+ do not map multipliers to MISTRAL_MUL cells
+
+ -noiopad
+ do not instantiate IO buffers
+
+ -noclkbuf
+ do not insert global clock buffers
+
+The following commands are executed by this synthesis command:
+
+ begin:
+ read_verilog -specify -lib -D <family> +/intel_alm/common/alm_sim.v
+ read_verilog -specify -lib -D <family> +/intel_alm/common/dff_sim.v
+ read_verilog -specify -lib -D <family> +/intel_alm/common/dsp_sim.v
+ read_verilog -specify -lib -D <family> +/intel_alm/common/mem_sim.v
+ read_verilog -specify -lib -D <family> +/intel_alm/common/misc_sim.v
+ read_verilog -specify -lib -D <family> -icells +/intel_alm/common/abc9_model.v
+ read_verilog -lib +/intel/common/altpll_bb.v
+ read_verilog -lib +/intel_alm/common/megafunction_bb.v
+ hierarchy -check -top <top>
+
+ coarse:
+ proc
+ flatten (skip if -noflatten)
+ tribuf -logic
+ deminout
+ opt_expr
+ opt_clean
+ check
+ opt -nodffe -nosdff
+ fsm
+ opt
+ wreduce
+ peepopt
+ opt_clean
+ share
+ techmap -map +/cmp2lut.v -D LUT_WIDTH=6
+ opt_expr
+ opt_clean
+ techmap -map +/mul2dsp.v [...] (unless -nodsp)
+ alumacc
+ iopadmap -bits -outpad MISTRAL_OB I:PAD -inpad MISTRAL_IB O:PAD -toutpad MISTRAL_IO OE:O:PAD -tinoutpad MISTRAL_IO OE:O:I:PAD A:top (unless -noiopad)
+ techmap -map +/intel_alm/common/arith_alm_map.v -map +/intel_alm/common/dsp_map.v
+ opt
+ memory -nomap
+ opt_clean
+
+ map_bram: (skip if -nobram)
+ memory_bram -rules +/intel_alm/common/bram_<bram_type>.txt
+ techmap -map +/intel_alm/common/bram_<bram_type>_map.v
+
+ map_lutram: (skip if -nolutram)
+ memory_bram -rules +/intel_alm/common/lutram_mlab.txt (for Cyclone V / Cyclone 10GX)
+
+ map_ffram:
+ memory_map
+ opt -full
+
+ map_ffs:
+ techmap
+ dfflegalize -cell $_DFFE_PN0P_ 0 -cell $_SDFFCE_PP0P_ 0
+ techmap -map +/intel_alm/common/dff_map.v
+ opt -full -undriven -mux_undef
+ clean -purge
+ clkbufmap -buf MISTRAL_CLKBUF Q:A (unless -noclkbuf)
+
+ map_luts:
+ techmap -map +/intel_alm/common/abc9_map.v
+ abc9 [-dff] -maxlut 6 -W 600
+ techmap -map +/intel_alm/common/abc9_unmap.v
+ techmap -map +/intel_alm/common/alm_map.v
+ opt -fast
+ autoname
+ clean
+
+ check:
+ hierarchy -check
+ stat
+ check
+ blackbox =A:whitebox
+
+ quartus:
+ rename -hide w:*[* w:*]*
+ setundef -zero
+ hilomap -singleton -hicell __MISTRAL_VCC Q -locell __MISTRAL_GND Q
+ techmap -D <family> -map +/intel_alm/common/quartus_rename.v
+
+ vqm:
+ write_verilog -attr2comment -defparam -nohex -decimal <file-name>
+\end{lstlisting}
+
+\section{synth\_machxo2 -- synthesis for MachXO2 FPGAs. This work is experimental.}
+\label{cmd:synth_machxo2}
+\begin{lstlisting}[numbers=left,frame=single]
+ synth_machxo2 [options]
+
+This command runs synthesis for MachXO2 FPGAs.
+
+ -top <module>
+ use the specified module as top module
+
+ -blif <file>
+ write the design to the specified BLIF file. writing of an output file
+ is omitted if this parameter is not specified.
+
+ -edif <file>
+ write the design to the specified EDIF file. writing of an output file
+ is omitted if this parameter is not specified.
+
+ -json <file>
+ write the design to the specified JSON file. writing of an output file
+ is omitted if this parameter is not specified.
+
+ -run <from_label>:<to_label>
+ only run the commands between the labels (see below). an empty
+ from label is synonymous to 'begin', and empty to label is
+ synonymous to the end of the command list.
+
+ -noflatten
+ do not flatten design before synthesis
+
+ -noiopad
+ do not insert IO buffers
+
+ -vpr
+ generate an output netlist (and BLIF file) suitable for VPR
+ (this feature is experimental and incomplete)
+
+
+The following commands are executed by this synthesis command:
+
+ begin:
+ read_verilog -lib -icells +/machxo2/cells_sim.v
+ hierarchy -check -top <top>
+
+ flatten: (unless -noflatten)
+ proc
+ flatten
+ tribuf -logic
+ deminout
+
+ coarse:
+ synth -run coarse
+
+ fine:
+ memory_map
+ opt -full
+ techmap -map +/techmap.v
+ opt -fast
+
+ map_ios: (unless -noiopad)
+ iopadmap -bits -outpad $__FACADE_OUTPAD I:O -inpad $__FACADE_INPAD O:I -toutpad $__FACADE_TOUTPAD ~T:I:O -tinoutpad $__FACADE_TINOUTPAD ~T:O:I:B A:top
+ attrmvcp -attr src -attr LOC t:$__FACADE_OUTPAD %x:+[O] t:$__FACADE_TOUTPAD %x:+[O] t:$__FACADE_TINOUTPAD %x:+[B]
+ attrmvcp -attr src -attr LOC -driven t:$__FACADE_INPAD %x:+[I]
+
+ map_ffs:
+ dfflegalize -cell $_DFF_P_ 0
+
+ map_luts:
+ abc -lut 4 -dress
+ clean
+
+ map_cells:
+ techmap -map +/machxo2/cells_map.v
+ clean
+
+ check:
+ hierarchy -check
+ stat
+ blackbox =A:whitebox
+
+ blif:
+ opt_clean -purge (vpr mode)
+ write_blif -attr -cname -conn -param <file-name> (vpr mode)
+ write_blif -gates -attr -param <file-name> (non-vpr mode)
+
+ edif:
+ write_edif <file-name>
+
+ json:
+ write_json <file-name>
+\end{lstlisting}
+
+\section{synth\_nexus -- synthesis for Lattice Nexus FPGAs}
+\label{cmd:synth_nexus}
+\begin{lstlisting}[numbers=left,frame=single]
+ synth_nexus [options]
+
+This command runs synthesis for Lattice Nexus FPGAs.
+
+ -top <module>
+ use the specified module as top module
+
+ -family <device>
+ run synthesis for the specified Nexus device
+ supported values: lifcl, lfd2nx
+
+ -json <file>
+ write the design to the specified JSON file. writing of an output file
+ is omitted if this parameter is not specified.
+
+ -vm <file>
+ write the design to the specified structural Verilog file. writing of
+ an output file is omitted if this parameter is not specified.
+
+ -run <from_label>:<to_label>
+ only run the commands between the labels (see below). an empty
+ from label is synonymous to 'begin', and empty to label is
+ synonymous to the end of the command list.
+
+ -noflatten
+ do not flatten design before synthesis
+
+ -dff
+ run 'abc'/'abc9' with -dff option
+
+ -retime
+ run 'abc' with '-dff -D 1' options
+
+ -noccu2
+ do not use CCU2 cells in output netlist
+
+ -nodffe
+ do not use flipflops with CE in output netlist
+
+ -nolram
+ do not use large RAM cells in output netlist
+ note that large RAM must be explicitly requested with a (* lram *)
+ attribute on the memory.
+
+ -nobram
+ do not use block RAM cells in output netlist
+
+ -nolutram
+ do not use LUT RAM cells in output netlist
+
+ -nowidelut
+ do not use PFU muxes to implement LUTs larger than LUT4s
+
+ -noiopad
+ do not insert IO buffers
+
+ -nodsp
+ do not infer DSP multipliers
+
+ -abc9
+ use new ABC9 flow (EXPERIMENTAL)
+
+The following commands are executed by this synthesis command:
+
+ begin:
+ read_verilog -lib -specify +/nexus/cells_sim.v +/nexus/cells_xtra.v
+ hierarchy -check -top <top>
+
+ coarse:
+ proc
+ flatten
+ tribuf -logic
+ deminout
+ opt_expr
+ opt_clean
+ check
+ opt -nodffe -nosdff
+ fsm
+ opt
+ wreduce
+ peepopt
+ opt_clean
+ share
+ techmap -map +/cmp2lut.v -D LUT_WIDTH=4
+ opt_expr
+ opt_clean
+ techmap -map +/mul2dsp.v [...] (unless -nodsp)
+ techmap -map +/nexus/dsp_map.v (unless -nodsp)
+ alumacc
+ opt
+ memory -nomap
+ opt_clean
+
+ map_lram: (skip if -nolram)
+ memory_bram -rules +/nexus/lrams.txt
+ setundef -zero -params t:$__NX_PDPSC512K
+ techmap -map +/nexus/lrams_map.v
+
+ map_bram: (skip if -nobram)
+ memory_bram -rules +/nexus/brams.txt
+ setundef -zero -params t:$__NX_PDP16K
+ techmap -map +/nexus/brams_map.v
+
+ map_lutram: (skip if -nolutram)
+ memory_bram -rules +/nexus/lutrams.txt
+ setundef -zero -params t:$__NEXUS_DPR16X4
+ techmap -map +/nexus/lutrams_map.v
+
+ map_ffram:
+ opt -fast -mux_undef -undriven -fine
+ memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block -attr syn_ramstyle=auto -attr syn_ramstyle=registers -attr syn_romstyle=auto -attr syn_romstyle=logic
+ opt -undriven -fine
+
+ map_gates:
+ techmap -map +/techmap.v -map +/nexus/arith_map.v
+ iopadmap -bits -outpad OB I:O -inpad IB O:I -toutpad OBZ ~T:I:O -tinoutpad BB ~T:O:I:B A:top (skip if '-noiopad')
+ opt -fast
+ abc -dff -D 1 (only if -retime)
+
+ map_ffs:
+ opt_clean
+ dfflegalize -cell $_DFF_P_ 01 -cell $_DFF_PP?_ r -cell $_SDFF_PP?_ r -cell $_DLATCH_?_ x [-cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r] ($_*DFFE_* only if not -nodffe)
+ zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF* (only if -abc9 and -dff
+ techmap -D NO_LUT -map +/nexus/cells_map.v
+ opt_expr -undriven -mux_undef
+ simplemap
+ attrmvcp -copy -attr syn_useioff
+ opt_clean
+
+ map_luts:
+ techmap -map +/nexus/latches_map.v
+ abc -dress -lut 4:5
+ clean
+
+ map_cells:
+ techmap -map +/nexus/cells_map.v
+ setundef -zero
+ hilomap -singleton -hicell VHI Z -locell VLO Z
+ clean
+
+ check:
+ autoname
+ hierarchy -check
+ stat
+ check -noinit
+ blackbox =A:whitebox
+
+ json:
+ write_json <file-name>
+
+ vm:
+ write_verilog <file-name>
+\end{lstlisting}
+
+\section{synth\_quicklogic -- Synthesis for QuickLogic FPGAs}
+\label{cmd:synth_quicklogic}
+\begin{lstlisting}[numbers=left,frame=single]
+ synth_quicklogic [options]
+This command runs synthesis for QuickLogic FPGAs
+
+ -top <module>
+ use the specified module as top module
+
+ -family <family>
+ run synthesis for the specified QuickLogic architecture
+ generate the synthesis netlist for the specified family.
+ supported values:
+ - pp3: PolarPro 3
+
+ -blif <file>
+ write the design to the specified BLIF file. writing of an output file
+ is omitted if this parameter is not specified.
+
+ -verilog <file>
+ write the design to the specified verilog file. writing of an output file
+ is omitted if this parameter is not specified.
+
+ -abc
+ use old ABC flow, which has generally worse mapping results but is less
+ likely to have bugs.
+
+The following commands are executed by this synthesis command:
+
+ begin:
+ read_verilog -lib -specify +/quicklogic/cells_sim.v +/quicklogic/pp3_cells_sim.v
+ read_verilog -lib -specify +/quicklogic/lut_sim.v
+ hierarchy -check -top <top>
+
+ coarse:
+ proc
+ flatten
+ tribuf -logic
+ deminout
+ opt_expr
+ opt_clean
+ check
+ opt -nodffe -nosdff
+ fsm
+ opt
+ wreduce
+ peepopt
+ opt_clean
+ share
+ techmap -map +/cmp2lut.v -D LUT_WIDTH=4
+ opt_expr
+ opt_clean
+ alumacc
+ pmuxtree
+ opt
+ memory -nomap
+ opt_clean
+
+ map_ffram:
+ opt -fast -mux_undef -undriven -fine
+ memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block -attr syn_ramstyle=auto -attr syn_ramstyle=registers -attr syn_romstyle=auto -attr syn_romstyle=logic
+ opt -undriven -fine
+
+ map_gates:
+ techmap
+ opt -fast
+ muxcover -mux8 -mux4
+
+ map_ffs:
+ opt_expr
+ dfflegalize -cell $_DFFSRE_PPPP_ 0 -cell $_DLATCH_?_ x
+ techmap -map +/quicklogic/pp3_cells_map.v -map +/quicklogic/pp3_ffs_map.v
+ opt_expr -mux_undef
+
+ map_luts:
+ techmap -map +/quicklogic/pp3_latches_map.v
+ read_verilog -lib -specify -icells +/quicklogic/abc9_model.v
+ techmap -map +/quicklogic/abc9_map.v
+ abc9 -maxlut 4 -dff
+ techmap -map +/quicklogic/abc9_unmap.v
+ clean
+
+ map_cells:
+ techmap -map +/quicklogic/pp3_lut_map.v
+ clean
+
+ check:
+ autoname
+ hierarchy -check
+ stat
+ check -noinit
+
+ iomap:
+ clkbufmap -inpad ckpad Q:P
+ iopadmap -bits -outpad outpad A:P -inpad inpad Q:P -tinoutpad bipad EN:Q:A:P A:top
+
+ finalize:
+ setundef -zero -params -undriven
+ hilomap -hicell logic_1 A -locell logic_0 A -singleton A:top
+ opt_clean -purge
+ check
+ blackbox =A:whitebox
+
+ blif:
+ write_blif -attr -param -auto-top
+
+ verilog:
+ write_verilog -noattr -nohex <file-name>
+\end{lstlisting}
+
\section{synth\_sf2 -- synthesis for SmartFusion2 and IGLOO2 FPGAs}
\label{cmd:synth_sf2}
\begin{lstlisting}[numbers=left,frame=single]
@@ -5907,6 +6903,7 @@ The following commands are executed by this synthesis command:
abc -dff -D 1 (only if -retime)
map_ffs:
+ dfflegalize -cell $_DFFE_PN?P_ x -cell $_SDFFCE_PN?P_ x -cell $_DLATCH_PN?_ x
techmap -D NO_LUT -map +/sf2/cells_map.v
opt_expr -mux_undef
simplemap
@@ -5920,13 +6917,15 @@ The following commands are executed by this synthesis command:
clean
map_iobs:
- sf2_iobs [-clkbuf] (unless -noiobs)
+ clkbufmap -buf CLKINT Y:A [-inpad CLKBUF Y:PAD] (unless -noiobs, -inpad only passed if -clkbuf)
+ iopadmap -bits -inpad INBUF Y:PAD -outpad OUTBUF D:PAD -toutpad TRIBUFF E:D:PAD -tinoutpad BIBUF E:Y:D:PAD (unless -noiobs
clean
check:
hierarchy -check
stat
check -noinit
+ blackbox =A:whitebox
edif:
write_edif -gndvccy <file-name>
@@ -5978,10 +6977,6 @@ compatible with 7-Series Xilinx devices.
write the design to the specified BLIF file. writing of an output file
is omitted if this parameter is not specified.
- -vpr
- generate an output netlist (and BLIF file) suitable for VPR
- (this feature is experimental and incomplete)
-
-ise
generate an output netlist suitable for ISE
@@ -6052,6 +7047,8 @@ The following commands are executed by this synthesis command:
opt_expr
opt_clean
check
+ opt -nodffe -nosdff
+ fsm
opt
wreduce [-keepdc] (option for '-widemux')
peepopt
@@ -6076,8 +7073,6 @@ The following commands are executed by this synthesis command:
alumacc
share
opt
- fsm
- opt -fast
memory -nomap
opt_clean
@@ -6094,33 +7089,34 @@ The following commands are executed by this synthesis command:
techmap -map +/xilinx/lutrams_map.v
map_ffram:
- simplemap t:$dff t:$adff t:$mux
- dff2dffs [-match-init] (-match-init for xc6s only)
opt -fast -full
memory_map
fine:
- dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*
- muxcover <internal options> ('-widemux' only)
+ simplemap t:$mux ('-widemux' only)
+ muxcover <internal options> ('-widemux' only)
opt -full
xilinx_srl -variable -minlen 3 (skip if '-nosrl')
techmap -map +/techmap.v -D LUT_SIZE=[46] [-map +/xilinx/mux_map.v] -map +/xilinx/arith_map.v
opt -fast
map_cells:
- iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad $__XILINX_TOUTPAD OE:I:O -tinoutpad $__XILINX_TINOUTPAD OE:O:I:IO A:top (skip if '-noiopad')
+ iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad OBUFT ~T:I:O -tinoutpad IOBUF ~T:O:I:IO A:top (skip if '-noiopad')
techmap -map +/techmap.v -map +/xilinx/cells_map.v
clean
map_ffs:
- techmap -map +/xilinx/{family}_ff_map.v ('-abc9' only)
+ dfflegalize -cell $_DFFE_?P?P_ 01 -cell $_SDFFE_?P?P_ 01 -cell $_DLATCH_?P?_ 01 (for xc6v, xc7, xcu, xcup)
+ zinit -all w:* t:$_SDFFE_* ('-dff' only)
+ techmap -map +/xilinx/ff_map.v ('-abc9' only)
map_luts:
- opt_expr -mux_undef
- abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1] (option for 'nowidelut', '-dff', '-retime')
+ opt_expr -mux_undef -noclkinv
+ abc -luts 2:2,3,6:5[,10,20] [-dff] [-D 1] (option for '-nowidelut', '-dff', '-retime')
clean
+ techmap -map +/xilinx/ff_map.v (only if not '-abc9')
xilinx_srl -fixed -minlen 3 (skip if '-nosrl')
- techmap -map +/xilinx/lut_map.v -map +/xilinx/cells_map.v -map +/xilinx/{family}_ff_map.v -D LUT_WIDTH=[46]
+ techmap -map +/xilinx/lut_map.v -map +/xilinx/cells_map.v -D LUT_WIDTH=[46]
xilinx_dffopt [-lut4]
opt_lut_ins -tech xilinx
@@ -6133,6 +7129,7 @@ The following commands are executed by this synthesis command:
hierarchy -check
stat -tech xilinx
check -noinit
+ blackbox =A:whitebox
edif:
write_edif -pvector bra
@@ -6164,7 +7161,7 @@ the standard $argc and $argv variables.
techmap [-map filename] [selection]
This pass implements a very simple technology mapper that replaces cells in
-the design with implementations given in form of a Verilog or ilang source
+the design with implementations given in form of a Verilog or RTLIL source
file.
-map filename
@@ -6207,7 +7204,9 @@ file.
When a module in the map file has the 'techmap_celltype' attribute set, it will
match cells with a type that match the text value of this attribute. Otherwise
-the module name will be used to match the cell.
+the module name will be used to match the cell. Multiple space-separated cell
+types can be listed, and wildcards using [] will be expanded (ie. "$_DFF_[PN]_"
+is the same as "$_DFF_P_ $_DFF_N_").
When a module in the map file has the 'techmap_simplemap' attribute set, techmap
will use 'simplemap' (see 'help simplemap') to map cells matching the module.
@@ -6276,6 +7275,10 @@ modules in the map file:
When a parameter with this name exists, it will be set to the type name
of the cell that matches the module.
+ _TECHMAP_CELLNAME_
+ When a parameter with this name exists, it will be set to the name
+ of the cell that matches the module.
+
_TECHMAP_CONSTMSK_<port-name>_
_TECHMAP_CONSTVAL_<port-name>_
When this pair of parameters is available in a module for a port, then
@@ -6401,12 +7404,12 @@ cell types. Use for example 'all /$add' for all cell types except $add.
-s {positive_integer}
use this value as rng seed value (default = unix time).
- -f {ilang_file}
- don't generate circuits. instead load the specified ilang file.
+ -f {rtlil_file}
+ don't generate circuits. instead load the specified RTLIL file.
-w {filename_prefix}
don't test anything. just generate the circuits and write them
- to ilang files with the specified prefix
+ to RTLIL files with the specified prefix
-map {filename}
pass this option to techmap.
@@ -6535,7 +7538,7 @@ different compilation units.
Additional -D<macro>[=<value>] options may be added after the option indicating
the language version (and before file names) to set additional verilog defines.
-The macros SYNTHESIS and VERIFIC are defined implicitly.
+The macros YOSYS, SYNTHESIS, and VERIFIC are defined implicitly.
verific -formal <verilog-file>..
@@ -6548,6 +7551,32 @@ Like -sv, but define FORMAL instead of SYNTHESIS.
Load the specified VHDL files into Verific.
+ verific {-f|-F} <command-file>
+
+Load and execute the specified command file.
+
+Command file parser supports following commands:
+ +define - defines macro
+ -u - upper case all identifier (makes Verilog parser case insensitive)
+ -v - register library name (file)
+ -y - register library name (directory)
+ +incdir - specify include dir
+ +libext - specify library extension
+ +liborder - add library in ordered list
+ +librescan - unresolved modules will be always searched starting with the first
+ library specified by -y/-v options.
+ -f/-file - nested -f option
+ -F - nested -F option
+
+ parse mode:
+ -ams
+ +systemverilogext
+ +v2k
+ +verilog1995ext
+ +verilog2001ext
+ -sverilog
+
+
verific [-work <libname>] {-sv|-vhdl|...} <hdl-file>
Load the specified Verilog/SystemVerilog/VHDL file into the specified library.
@@ -6652,11 +7681,74 @@ bindings (for Yosys and/or Verific developers):
Dump the Verific netlist as a verilog file.
-Use Symbiotic EDA Suite if you need Yosys+Verifc.
-https://www.symbioticeda.com/seda-suite
+ verific [-work <libname>] -pp [options] <filename> [<module>]..
+
+Pretty print design (or just module) to the specified file from the
+specified library. (default library when -work is not present: "work")
+
+Pretty print options:
+
+ -verilog
+ Save output for Verilog/SystemVerilog design modules (default).
+
+ -vhdl
+ Save output for VHDL design units.
+
+
+ verific -app <application>..
+
+Execute YosysHQ formal application on loaded Verilog files.
+
+Application options:
+
+ -module <module>
+ Run formal application only on specified module.
+
+ -blacklist <filename[:lineno]>
+ Do not run application on modules from files that match the filename
+ or filename and line number if provided in such format.
+ Parameter can also contain comma separated list of file locations.
+
+ -blfile <file>
+ Do not run application on locations specified in file, they can represent filename
+ or filename and location in file.
-Contact office@symbioticeda.com for free evaluation
-binaries of Symbiotic EDA Suite.
+Applications:
+
+ WARNING: Applications only available in commercial build.
+
+
+ verific -template <name> <top_module>..
+
+Generate template for specified top module of loaded design.
+
+Template options:
+
+ -out
+ Specifies output file for generated template, by default output is stdout
+
+ -chparam name value
+ Generate template using this parameter value. Otherwise default parameter
+ values will be used for templat generate functionality. This option
+ can be specified multiple times to override multiple parameters.
+ String values must be passed in double quotes (").
+
+Templates:
+
+ WARNING: Templates only available in commercial build.
+
+
+
+ verific -cfg [<name> [<value>]]
+
+Get/set Verific runtime flags.
+
+
+Use YosysHQ Tabby CAD Suite if you need Yosys+Verific.
+https://www.yosyshq.com/
+
+Contact office@yosyshq.com for free evaluation
+binaries of YosysHQ Tabby CAD Suite.
\end{lstlisting}
\section{verilog\_defaults -- set default options for read\_verilog}
@@ -6855,6 +7947,9 @@ Write a BTOR description of the current design.
-i <filename>
Create additional info file with auxiliary information
+
+ -x
+ Output symbols for internal netnames (starting with '$')
\end{lstlisting}
\section{write\_cxxrtl -- convert design to C++ RTL simulation}
@@ -6862,25 +7957,189 @@ Write a BTOR description of the current design.
\begin{lstlisting}[numbers=left,frame=single]
write_cxxrtl [options] [filename]
-Write C++ code for simulating the design. The generated code requires a driver;
-the following simple driver is provided as an example:
+Write C++ code that simulates the design. The generated code requires a driver
+that instantiates the design, toggles its clock, and interacts with its ports.
+
+The following driver may be used as an example for a design with a single clock
+driving rising edge triggered flip-flops:
#include "top.cc"
int main() {
cxxrtl_design::p_top top;
+ top.step();
while (1) {
- top.p_clk.next = value<1> {1u};
+ /* user logic */
+ top.p_clk.set(false);
top.step();
- top.p_clk.next = value<1> {0u};
+ top.p_clk.set(true);
top.step();
}
}
+Note that CXXRTL simulations, just like the hardware they are simulating, are
+subject to race conditions. If, in the example above, the user logic would run
+simultaneously with the rising edge of the clock, the design would malfunction.
+
+This backend supports replacing parts of the design with black boxes implemented
+in C++. If a module marked as a CXXRTL black box, its implementation is ignored,
+and the generated code consists only of an interface and a factory function.
+The driver must implement the factory function that creates an implementation of
+the black box, taking into account the parameters it is instantiated with.
+
+For example, the following Verilog code defines a CXXRTL black box interface for
+a synchronous debug sink:
+
+ (* cxxrtl_blackbox *)
+ module debug(...);
+ (* cxxrtl_edge = "p" *) input clk;
+ input en;
+ input [7:0] i_data;
+ (* cxxrtl_sync *) output [7:0] o_data;
+ endmodule
+
+For this HDL interface, this backend will generate the following C++ interface:
+
+ struct bb_p_debug : public module {
+ value<1> p_clk;
+ bool posedge_p_clk() const { /* ... */ }
+ value<1> p_en;
+ value<8> p_i_data;
+ wire<8> p_o_data;
+
+ bool eval() override;
+ bool commit() override;
+
+ static std::unique_ptr<bb_p_debug>
+ create(std::string name, metadata_map parameters, metadata_map attributes);
+ };
+
+The `create' function must be implemented by the driver. For example, it could
+always provide an implementation logging the values to standard error stream:
+
+ namespace cxxrtl_design {
+
+ struct stderr_debug : public bb_p_debug {
+ bool eval() override {
+ if (posedge_p_clk() && p_en)
+ fprintf(stderr, "debug: %02x\n", p_i_data.data[0]);
+ p_o_data.next = p_i_data;
+ return bb_p_debug::eval();
+ }
+ };
+
+ std::unique_ptr<bb_p_debug>
+ bb_p_debug::create(std::string name, cxxrtl::metadata_map parameters,
+ cxxrtl::metadata_map attributes) {
+ return std::make_unique<stderr_debug>();
+ }
+
+ }
+
+For complex applications of black boxes, it is possible to parameterize their
+port widths. For example, the following Verilog code defines a CXXRTL black box
+interface for a configurable width debug sink:
+
+ (* cxxrtl_blackbox, cxxrtl_template = "WIDTH" *)
+ module debug(...);
+ parameter WIDTH = 8;
+ (* cxxrtl_edge = "p" *) input clk;
+ input en;
+ (* cxxrtl_width = "WIDTH" *) input [WIDTH - 1:0] i_data;
+ (* cxxrtl_width = "WIDTH" *) output [WIDTH - 1:0] o_data;
+ endmodule
+
+For this parametric HDL interface, this backend will generate the following C++
+interface (only the differences are shown):
+
+ template<size_t WIDTH>
+ struct bb_p_debug : public module {
+ // ...
+ value<WIDTH> p_i_data;
+ wire<WIDTH> p_o_data;
+ // ...
+ static std::unique_ptr<bb_p_debug<WIDTH>>
+ create(std::string name, metadata_map parameters, metadata_map attributes);
+ };
+
+The `create' function must be implemented by the driver, specialized for every
+possible combination of template parameters. (Specialization is necessary to
+enable separate compilation of generated code and black box implementations.)
+
+ template<size_t SIZE>
+ struct stderr_debug : public bb_p_debug<SIZE> {
+ // ...
+ };
+
+ template<>
+ std::unique_ptr<bb_p_debug<8>>
+ bb_p_debug<8>::create(std::string name, cxxrtl::metadata_map parameters,
+ cxxrtl::metadata_map attributes) {
+ return std::make_unique<stderr_debug<8>>();
+ }
+
+The following attributes are recognized by this backend:
+
+ cxxrtl_blackbox
+ only valid on modules. if specified, the module contents are ignored,
+ and the generated code includes only the module interface and a factory
+ function, which will be called to instantiate the module.
+
+ cxxrtl_edge
+ only valid on inputs of black boxes. must be one of "p", "n", "a".
+ if specified on signal `clk`, the generated code includes edge detectors
+ `posedge_p_clk()` (if "p"), `negedge_p_clk()` (if "n"), or both (if
+ "a"), simplifying implementation of clocked black boxes.
+
+ cxxrtl_template
+ only valid on black boxes. must contain a space separated sequence of
+ identifiers that have a corresponding black box parameters. for each
+ of them, the generated code includes a `size_t` template parameter.
+
+ cxxrtl_width
+ only valid on ports of black boxes. must be a constant expression, which
+ is directly inserted into generated code.
+
+ cxxrtl_comb, cxxrtl_sync
+ only valid on outputs of black boxes. if specified, indicates that every
+ bit of the output port is driven, correspondingly, by combinatorial or
+ synchronous logic. this knowledge is used for scheduling optimizations.
+ if neither is specified, the output will be pessimistically treated as
+ driven by both combinatorial and synchronous logic.
+
The following options are supported by this backend:
+ -print-wire-types, -print-debug-wire-types
+ enable additional debug logging, for pass developers.
+
+ -header
+ generate separate interface (.h) and implementation (.cc) files.
+ if specified, the backend must be called with a filename, and filename
+ of the interface is derived from filename of the implementation.
+ otherwise, interface and implementation are generated together.
+
+ -namespace <ns-name>
+ place the generated code into namespace <ns-name>. if not specified,
+ "cxxrtl_design" is used.
+
+ -nohierarchy
+ use design hierarchy as-is. in most designs, a top module should be
+ present as it is exposed through the C API and has unbuffered outputs
+ for improved performance; it will be determined automatically if absent.
+
+ -noflatten
+ don't flatten the design. fully flattened designs can evaluate within
+ one delta cycle if they have no combinatorial feedback.
+ note that the debug interface and waveform dumps use full hierarchical
+ names for all wires even in flattened designs.
+
+ -noproc
+ don't convert processes to netlists. in most designs, converting
+ processes significantly improves evaluation performance at the cost of
+ slight increase in compilation time.
+
-O <level>
- set the optimization level. the default is -O5. higher optimization
+ set the optimization level. the default is -O6. higher optimization
levels dramatically decrease compile and run time, and highest level
possible for a design should be used.
@@ -6888,19 +8147,45 @@ The following options are supported by this backend:
no optimization.
-O1
- elide internal wires if possible.
+ unbuffer internal wires if possible.
-O2
like -O1, and localize internal wires if possible.
-O3
- like -O2, and elide public wires not marked (*keep*) if possible.
+ like -O2, and inline internal wires if possible.
-O4
- like -O3, and localize public wires not marked (*keep*) if possible.
+ like -O3, and unbuffer public wires not marked (*keep*) if possible.
-O5
- like -O4, and run `splitnets -driver; opt_clean -purge` first.
+ like -O4, and localize public wires not marked (*keep*) if possible.
+
+ -O6
+ like -O5, and inline public wires not marked (*keep*) if possible.
+
+ -g <level>
+ set the debug level. the default is -g4. higher debug levels provide
+ more visibility and generate more code, but do not pessimize evaluation.
+
+ -g0
+ no debug information. the C API is disabled.
+
+ -g1
+ include bare minimum of debug information necessary to access all design
+ state. the C API is enabled.
+
+ -g2
+ like -g1, but include debug information for all public wires that are
+ directly accessible through the C++ interface.
+
+ -g3
+ like -g2, and include debug information for public wires that are tied
+ to a constant or another public wire.
+
+ -g4
+ like -g3, and compute debug information on demand for all public wires
+ that were optimized out.
\end{lstlisting}
\section{write\_edif -- write design to EDIF netlist file}
@@ -6925,6 +8210,9 @@ Write the current design to an EDIF netlist file.
-attrprop
create EDIF properties for cell attributes
+ -keep
+ create extra KEEP nets by allowing a cell to drive multiple nets.
+
-pvector {par|bra|ang}
sets the delimiting character for module port rename clauses to
parentheses, square brackets, or angle brackets.
@@ -6961,18 +8249,14 @@ Inside a script the input file can also can a here-document:
Write a FIRRTL netlist of the current design.
The following commands are executed by this command:
pmuxtree
+ bmuxmap
+ demuxmap
\end{lstlisting}
-\section{write\_ilang -- write design to ilang file}
+\section{write\_ilang -- (deprecated) alias of write\_rtlil}
\label{cmd:write_ilang}
\begin{lstlisting}[numbers=left,frame=single]
- write_ilang [filename]
-
-Write the current design to an 'ilang' file. (ilang is a text representation
-of a design in yosys's internal format.)
-
- -selected
- only write selected parts of the design.
+See `help write_rtlil`.
\end{lstlisting}
\section{write\_intersynth -- write design to InterSynth netlist file}
@@ -6987,7 +8271,7 @@ a tool for Coarse-Grain Example-Driven Interconnect Synthesis.
do not generate celltypes and conntypes commands. i.e. just output
the netlists. this is used for postsilicon synthesis.
- -lib <verilog_or_ilang_file>
+ -lib <verilog_or_rtlil_file>
Use the specified library file for determining whether cell ports are
inputs or outputs. This option can be used multiple times to specify
more than one library.
@@ -6996,7 +8280,7 @@ a tool for Coarse-Grain Example-Driven Interconnect Synthesis.
only write selected modules. modules must be selected entirely or
not at all.
-http://www.clifford.at/intersynth/
+http://bygone.clairexen.net/intersynth/
\end{lstlisting}
\section{write\_json -- write design to a JSON file}
@@ -7017,8 +8301,17 @@ Write a JSON netlist of the current design.
The general syntax of the JSON output created by this command is as follows:
{
+ "creator": "Yosys <version info>",
"modules": {
<module_name>: {
+ "attributes": {
+ <attribute_name>: <attribute_value>,
+ ...
+ },
+ "parameter_default_values": {
+ <parameter_name>: <parameter_value>,
+ ...
+ },
"ports": {
<port_name>: <port_details>,
...
@@ -7027,6 +8320,10 @@ The general syntax of the JSON output created by this command is as follows:
<cell_name>: <cell_details>,
...
},
+ "memories": {
+ <memory_name>: <memory_details>,
+ ...
+ },
"netnames": {
<net_name>: <net_details>,
...
@@ -7043,13 +8340,16 @@ Where <port_details> is:
{
"direction": <"input" | "output" | "inout">,
"bits": <bit_vector>
+ "offset": <the lowest bit index in use, if non-0>
+ "upto": <1 if the port bit indexing is MSB-first>
}
-And <cell_details> is:
+The "offset" and "upto" fields are skipped if their value would be 0.They don't affect connection semantics, and are only used to preserve originalHDL bit indexing.And <cell_details> is:
{
"hide_name": <1 | 0>,
"type": <cell_type>,
+ "model": <AIG model name, if -aig option used>,
"parameters": {
<parameter_name>: <parameter_value>,
...
@@ -7068,11 +8368,26 @@ And <cell_details> is:
},
}
+And <memory_details> is:
+
+ {
+ "hide_name": <1 | 0>,
+ "attributes": {
+ <attribute_name>: <attribute_value>,
+ ...
+ },
+ "width": <memory width>
+ "start_offset": <the lowest valid memory address>
+ "size": <memory size>
+ }
+
And <net_details> is:
{
"hide_name": <1 | 0>,
"bits": <bit_vector>
+ "offset": <the lowest bit index in use, if non-0>
+ "upto": <1 if the port bit indexing is MSB-first>
}
The "hide_name" fields are set to 1 when the name of this cell or net is
@@ -7099,8 +8414,13 @@ For example the following Verilog code:
Translates to the following JSON output:
{
+ "creator": "Yosys 0.9+2406 (git sha1 fb1168d8, clang 9.0.1 -fPIC -Os)",
"modules": {
"test": {
+ "attributes": {
+ "cells_not_processed": "00000000000000000000000000000001",
+ "src": "test.v:1.1-4.10"
+ },
"ports": {
"x": {
"direction": "input",
@@ -7116,33 +8436,34 @@ Translates to the following JSON output:
"hide_name": 0,
"type": "foo",
"parameters": {
- "Q": 1337,
- "P": 42
+ "P": "00000000000000000000000000101010",
+ "Q": "00000000000000000000010100111001"
},
"attributes": {
- "keep": 1,
- "src": "test.v:2"
+ "keep": "00000000000000000000000000000001",
+ "module_not_derived": "00000000000000000000000000000001",
+ "src": "test.v:3.1-3.55"
},
"connections": {
- "C": [ 2, 2, 2, 2, "0", "1", "0", "1" ],
+ "A": [ 3, 2 ],
"B": [ 2, 3 ],
- "A": [ 3, 2 ]
+ "C": [ 2, 2, 2, 2, "0", "1", "0", "1" ]
}
}
},
"netnames": {
- "y": {
+ "x": {
"hide_name": 0,
- "bits": [ 3 ],
+ "bits": [ 2 ],
"attributes": {
- "src": "test.v:1"
+ "src": "test.v:1.19-1.20"
}
},
- "x": {
+ "y": {
"hide_name": 0,
- "bits": [ 2 ],
+ "bits": [ 3 ],
"attributes": {
- "src": "test.v:1"
+ "src": "test.v:1.22-1.23"
}
}
}
@@ -7208,6 +8529,18 @@ Future version of Yosys might add support for additional fields in the JSON
format. A program processing this format must ignore all unknown fields.
\end{lstlisting}
+\section{write\_rtlil -- write design to RTLIL file}
+\label{cmd:write_rtlil}
+\begin{lstlisting}[numbers=left,frame=single]
+ write_rtlil [filename]
+
+Write the current design to an RTLIL file. (RTLIL is a text representation
+of a design in yosys's internal format.)
+
+ -selected
+ only write selected parts of the design.
+\end{lstlisting}
+
\section{write\_simplec -- convert design to simple C code}
\label{cmd:write_simplec}
\begin{lstlisting}[numbers=left,frame=single]
@@ -7332,8 +8665,12 @@ Options:
use the given template file. the line containing only the token '%%'
is replaced with the regular output of this command.
+ -solver-option <option> <value>
+ emit a `; yosys-smt2-solver-option` directive for yosys-smtbmc to write
+ the given option as a `(set-option ...)` command in the SMT-LIBv2.
+
[1] For more information on SMT-LIBv2 visit http://smt-lib.org/ or read David
-R. Cok's tutorial: http://www.grammatech.com/resources/smt/SMTLIBTutorial.pdf
+R. Cok's tutorial: https://smtlib.github.io/jSMTLIB/SMTLIBTutorial.pdf
---------------------------------------------------------------------------
@@ -7415,6 +8752,10 @@ Write the current design to an SPICE netlist file.
-pos net_name
set the net name for constant 1 (default: Vdd)
+ -buf DC|subckt_name
+ set the name for jumper element (default: DC)
+ (used to connect different nets)
+
-nc_prefix
prefix for not-connected nets (default: _NC)
@@ -7452,6 +8793,9 @@ module inputs and outputs are output using cell type and port '-' and with
Write the current design to a Verilog file.
+ -sv
+ with this option, SystemVerilog constructs like always_comb are used
+
-norename
without this option all internal object names (the ones with a dollar
instead of a backslash prefix) are changed to short names in the
@@ -7493,6 +8837,9 @@ Write the current design to a Verilog file.
deactivates this feature and instead will write string constants
as binary numbers.
+ -simple-lhs
+ Connection assignments with simple left hand side without concatenations.
+
-extmem
instead of initializing memories using assignments to individual
elements, use the '$readmemh' function to read initialization data
@@ -7530,15 +8877,19 @@ this command is called on a design with RTLIL processes.
write_xaiger [options] [filename]
Write the top module (according to the (* top *) attribute or if only one module
-is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, $_ABC9_FF_, ornon (* abc9_box_id *) cells will be converted into psuedo-inputs and
-pseudo-outputs. Whitebox contents will be taken from the '<module-name>$holes'
-module, if it exists.
+is currently selected) to an XAIGER file. Any non $_NOT_, $_AND_, (optionally
+$_DFF_N_, $_DFF_P_), or non (* abc9_box *) cells will be converted into psuedo-
+inputs and pseudo-outputs. Whitebox contents will be taken from the equivalent
+module in the '$abc9_holes' design, if it exists.
-ascii
write ASCII version of AIGER format
-map <filename>
write an extra file with port and box symbols
+
+ -dff
+ write $_DFF_[NP]_ cells
\end{lstlisting}
\section{xilinx\_dffopt -- Xilinx: optimize FF control signal usage}
diff --git a/manual/literature.bib b/manual/literature.bib
index 372e882ac..86652eb46 100644
--- a/manual/literature.bib
+++ b/manual/literature.bib
@@ -1,7 +1,7 @@
@inproceedings{intersynth,
title={Example-driven interconnect synthesis for heterogeneous coarse-grain reconfigurable logic},
- author={Clifford Wolf and Johann Glaser and Florian Schupfer and Jan Haase and Christoph Grimm},
+ author={C. Wolf and Johann Glaser and Florian Schupfer and Jan Haase and Christoph Grimm},
booktitle={FDL Proceeding of the 2012 Forum on Specification and Design Languages},
pages={194--201},
year={2012}
@@ -9,7 +9,7 @@
@incollection{intersynthFdlBookChapter,
title={Methodology and Example-Driven Interconnect Synthesis for Designing Heterogeneous Coarse-Grain Reconfigurable Architectures},
- author={Johann Glaser and Clifford Wolf},
+ author={Johann Glaser and C. Wolf},
booktitle={Advances in Models, Methods, and Tools for Complex Chip Design --- Selected contributions from FDL'12},
editor={Jan Haase},
publisher={Springer},
@@ -18,14 +18,14 @@
}
@unpublished{BACC,
- author = {Clifford Wolf},
+ author = {C. Wolf},
title = {Design and Implementation of the Yosys Open SYnthesis Suite},
note = {Bachelor Thesis, Vienna University of Technology},
year = {2013}
}
@unpublished{VerilogFossEval,
- author = {Clifford Wolf},
+ author = {C. Wolf},
title = {Evaluation of Open Source Verilog Synthesis Tools for Feature-Completeness and Extensibility},
note = {Unpublished Student Research Paper, Vienna University of Technology},
year = {2012}
diff --git a/manual/manual.tex b/manual/manual.tex
index dac8b1000..1914df989 100644
--- a/manual/manual.tex
+++ b/manual/manual.tex
@@ -51,7 +51,7 @@
% Hyperlinks
\usepackage[colorlinks,hyperindex,plainpages=false,%
pdftitle={Yosys Manual},%
-pdfauthor={Clifford Wolf},%
+pdfauthor={Claire Xenia Wolf},%
%pdfkeywords={keyword},%
pdfpagelabels,%
pagebackref,%
@@ -137,7 +137,7 @@ bookmarksopen=false%
\bf\Huge Yosys Manual
\bigskip
-\large Clifford Wolf
+\large Claire Xenia Wolf
\end{center}
\vfil\null
diff --git a/manual/presentation.tex b/manual/presentation.tex
index 63b963bbd..7aba33c8b 100644
--- a/manual/presentation.tex
+++ b/manual/presentation.tex
@@ -80,8 +80,8 @@
\end{centering}}
\title{Yosys Open SYnthesis Suite}
-\author{Clifford Wolf}
-\institute{http://www.clifford.at/yosys/}
+\author{Claire Xenia Wolf}
+\institute{https://yosyshq.net/yosys/}
\usetheme{Madrid}
\usecolortheme{seagull}
@@ -124,7 +124,7 @@ writing extensions to Yosys using the C++ API.
\section{About me}
\begin{frame}{About me}
-Hi! I'm Clifford Wolf.
+Hi! I'm Claire Xenia Wolf.
\bigskip
I like writing open source software. For example:
diff --git a/manual/weblinks.bib b/manual/weblinks.bib
index d5f83315d..23ddbc38b 100644
--- a/manual/weblinks.bib
+++ b/manual/weblinks.bib
@@ -1,20 +1,20 @@
@misc{YosysGit,
- author = {Clifford Wolf},
+ author = {Claire Xenia Wolf},
title = {{Yosys Open SYnthesis Suite (YOSYS)}},
- note = {\url{http://github.com/cliffordwolf/yosys}}
+ note = {\url{http://github.com/YosysHQ/yosys}}
}
@misc{YosysTestsGit,
- author = {Clifford Wolf},
+ author = {Claire Xenia Wolf},
title = {{Yosys Test Bench}},
- note = {\url{http://github.com/cliffordwolf/yosys-tests}}
+ note = {\url{http://github.com/YosysHQ/yosys-tests}}
}
@misc{VlogHammer,
- author = {Clifford Wolf},
+ author = {Claire Xenia Wolf},
title = {{VlogHammer Verilog Synthesis Regression Tests}},
- note = {\url{http://github.com/cliffordwolf/VlogHammer}}
+ note = {\url{http://github.com/YosysHQ/VlogHammer}}
}
@misc{Icarus,
diff --git a/misc/create_vcxsrc.sh b/misc/create_vcxsrc.sh
index 924d2722e..e3c1ad991 100644
--- a/misc/create_vcxsrc.sh
+++ b/misc/create_vcxsrc.sh
@@ -6,12 +6,21 @@ yosysver="$2"
gitsha="$3"
rm -rf YosysVS-Tpl-v2.zip YosysVS
-wget http://www.clifford.at/yosys/nogit/YosysVS-Tpl-v2.zip
+wget https://yosyshq.net/yosys/nogit/YosysVS-Tpl-v2.zip
+wget https://zlib.net/zlib-1.2.11.tar.gz
unzip YosysVS-Tpl-v2.zip
rm -f YosysVS-Tpl-v2.zip
-mv YosysVS "$vcxsrc"
+tar xvfz zlib-1.2.11.tar.gz
+mv YosysVS "$vcxsrc"
+mkdir -p "$vcxsrc"/yosys
+mkdir -p "$vcxsrc"/yosys/libs/zlib
+mv zlib-1.2.11/* "$vcxsrc"/yosys/libs/zlib/.
+rm -rf zlib-1.2.11
+pushd "$vcxsrc"/yosys
+ls libs/zlib/*.c | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' >> ../../srcfiles.txt
+popd
{
n=$(grep -B999 '<ItemGroup>' "$vcxsrc"/YosysVS/YosysVS.vcxproj | wc -l)
head -n$n "$vcxsrc"/YosysVS/YosysVS.vcxproj
@@ -35,7 +44,7 @@ Want to use a git working copy for the yosys source code?
Open "Git Bash" in this directory and run:
mv yosys yosys.bak
- git clone https://github.com/cliffordwolf/yosys.git yosys
+ git clone https://github.com/YosysHQ/yosys.git yosys
cd yosys
git checkout -B master $(git rev-parse HEAD | cut -c1-10)
unzip ../genfiles.zip
diff --git a/misc/py_wrap_generator.py b/misc/py_wrap_generator.py
index 38bd6129e..4d9a60113 100644
--- a/misc/py_wrap_generator.py
+++ b/misc/py_wrap_generator.py
@@ -1,7 +1,7 @@
#
# yosys -- Yosys Open SYnthesis Suite
#
-# Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+# Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -997,7 +997,7 @@ sources = [
Source("kernel/cost",[])
]
-blacklist_methods = ["YOSYS_NAMESPACE::Pass::run_register", "YOSYS_NAMESPACE::Module::Pow", "YOSYS_NAMESPACE::Module::Bu0", "YOSYS_NAMESPACE::CaseRule::optimize"]
+blacklist_methods = ["YOSYS_NAMESPACE::Pass::run_register", "YOSYS_NAMESPACE::Module::Pow"]
enum_names = ["State","SyncType","ConstFlags"]
@@ -2243,7 +2243,7 @@ def gen_wrappers(filename, debug_level_ = 0):
"""/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/Makefile.inc b/passes/cmds/Makefile.inc
index 53bfd40c6..16a38b511 100644
--- a/passes/cmds/Makefile.inc
+++ b/passes/cmds/Makefile.inc
@@ -18,6 +18,7 @@ OBJS += passes/cmds/setattr.o
OBJS += passes/cmds/copy.o
OBJS += passes/cmds/splice.o
OBJS += passes/cmds/scc.o
+OBJS += passes/cmds/glift.o
OBJS += passes/cmds/torder.o
OBJS += passes/cmds/logcmd.o
OBJS += passes/cmds/tee.o
@@ -40,3 +41,5 @@ endif
OBJS += passes/cmds/scratchpad.o
OBJS += passes/cmds/logger.o
OBJS += passes/cmds/printattrs.o
+OBJS += passes/cmds/sta.o
+OBJS += passes/cmds/clean_zerowidth.o
diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc
index a2f4a9100..c09517254 100644
--- a/passes/cmds/add.cc
+++ b/passes/cmds/add.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/autoname.cc b/passes/cmds/autoname.cc
index 28d4012c4..6019c6153 100644
--- a/passes/cmds/autoname.cc
+++ b/passes/cmds/autoname.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -22,25 +22,20 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-int autoname_worker(Module *module)
+int autoname_worker(Module *module, const dict<Wire*, int>& wire_score)
{
dict<Cell*, pair<int, IdString>> proposed_cell_names;
dict<Wire*, pair<int, IdString>> proposed_wire_names;
- dict<Wire*, int> wire_score;
int best_score = -1;
- for (auto cell : module->selected_cells())
- for (auto &conn : cell->connections())
- for (auto bit : conn.second)
- if (bit.wire != nullptr)
- wire_score[bit.wire]++;
-
for (auto cell : module->selected_cells()) {
if (cell->name[0] == '$') {
for (auto &conn : cell->connections()) {
- string suffix = stringf("_%s_%s", log_id(cell->type), log_id(conn.first));
+ string suffix;
for (auto bit : conn.second)
if (bit.wire != nullptr && bit.wire->name[0] != '$') {
+ if (suffix.empty())
+ suffix = stringf("_%s_%s", log_id(cell->type), log_id(conn.first));
IdString new_name(bit.wire->name.str() + suffix);
int score = wire_score.at(bit.wire);
if (cell->output(conn.first)) score = 0;
@@ -54,9 +49,11 @@ int autoname_worker(Module *module)
}
} else {
for (auto &conn : cell->connections()) {
- string suffix = stringf("_%s", log_id(conn.first));
+ string suffix;
for (auto bit : conn.second)
if (bit.wire != nullptr && bit.wire->name[0] == '$' && !bit.wire->port_id) {
+ if (suffix.empty())
+ suffix = stringf("_%s", log_id(conn.first));
IdString new_name(cell->name.str() + suffix);
int score = wire_score.at(bit.wire);
if (cell->output(conn.first)) score = 0;
@@ -118,10 +115,17 @@ struct AutonamePass : public Pass {
for (auto module : design->selected_modules())
{
+ dict<Wire*, int> wire_score;
+ for (auto cell : module->selected_cells())
+ for (auto &conn : cell->connections())
+ for (auto bit : conn.second)
+ if (bit.wire != nullptr)
+ wire_score[bit.wire]++;
+
int count = 0, iter = 0;
while (1) {
iter++;
- int n = autoname_worker(module);
+ int n = autoname_worker(module, wire_score);
if (!n) break;
count += n;
}
diff --git a/passes/cmds/blackbox.cc b/passes/cmds/blackbox.cc
index 08a635514..43670efaf 100644
--- a/passes/cmds/blackbox.cc
+++ b/passes/cmds/blackbox.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -46,10 +46,11 @@ struct BlackboxPass : public Pass {
}
extra_args(args, argidx, design);
- for (auto module : design->selected_whole_modules_warn())
+ for (auto module : design->selected_whole_modules_warn(true))
{
module->makeblackbox();
module->set_bool_attribute(ID::blackbox);
+ module->set_bool_attribute(ID::whitebox, false);
}
}
} BlackboxPass;
diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc
index da81e7f09..7b621504d 100644
--- a/passes/cmds/bugpoint.cc
+++ b/passes/cmds/bugpoint.cc
@@ -38,6 +38,8 @@ struct BugpointPass : public Pass {
log("and the same script, repeating these steps while it can find a smaller design that\n");
log("still causes a crash. Once this command finishes, it replaces the current design\n");
log("with the smallest testcase it was able to produce.\n");
+ log("In order to save the reduced testcase you must write this out to a file with\n");
+ log("another command after `bugpoint` like `write_rtlil` or `write_verilog`.\n");
log("\n");
log(" -script <filename> | -command \"<command>\"\n");
log(" use this script file or command to crash Yosys. required.\n");
@@ -87,9 +89,12 @@ struct BugpointPass : public Pass {
log(" -updates\n");
log(" try to remove process updates from syncs.\n");
log("\n");
+ log(" -runner \"<prefix>\"\n");
+ log(" child process wrapping command, e.g., \"timeout 30\", or valgrind.\n");
+ log("\n");
}
- bool run_yosys(RTLIL::Design *design, string yosys_cmd, string yosys_arg)
+ bool run_yosys(RTLIL::Design *design, string runner, string yosys_cmd, string yosys_arg)
{
design->sort();
@@ -97,7 +102,7 @@ struct BugpointPass : public Pass {
RTLIL_BACKEND::dump_design(f, design, /*only_selected=*/false, /*flag_m=*/true, /*flag_n=*/false);
f.close();
- string yosys_cmdline = stringf("%s -qq -L bugpoint-case.log %s bugpoint-case.il", yosys_cmd.c_str(), yosys_arg.c_str());
+ string yosys_cmdline = stringf("%s %s -qq -L bugpoint-case.log %s bugpoint-case.il", runner.c_str(), yosys_cmd.c_str(), yosys_arg.c_str());
return run_command(yosys_cmdline) == 0;
}
@@ -270,7 +275,7 @@ struct BugpointPass : public Pass {
if (mod->get_blackbox_attribute())
continue;
- RTLIL::IdString removed_process;
+ RTLIL::Process *removed_process = nullptr;
for (auto process : mod->processes)
{
if (process.second->get_bool_attribute(ID::bugpoint_keep))
@@ -279,13 +284,12 @@ struct BugpointPass : public Pass {
if (index++ == seed)
{
log_header(design, "Trying to remove process %s.%s.\n", log_id(mod), log_id(process.first));
- removed_process = process.first;
+ removed_process = process.second;
break;
}
}
- if (!removed_process.empty()) {
- delete mod->processes[removed_process];
- mod->processes.erase(removed_process);
+ if (removed_process) {
+ mod->remove(removed_process);
return design_copy;
}
}
@@ -339,6 +343,23 @@ struct BugpointPass : public Pass {
return design_copy;
}
}
+ int i = 0;
+ for (auto it = sy->mem_write_actions.begin(); it != sy->mem_write_actions.end(); ++it, ++i)
+ {
+ if (index++ == seed)
+ {
+ log_header(design, "Trying to remove sync %s memwr %s %s %s %s in %s.%s.\n", log_signal(sy->signal), log_id(it->memid), log_signal(it->address), log_signal(it->data), log_signal(it->enable), log_id(mod), log_id(pr.first));
+ sy->mem_write_actions.erase(it);
+ // Remove the bit for removed action from other actions' priority masks.
+ for (auto it2 = sy->mem_write_actions.begin(); it2 != sy->mem_write_actions.end(); ++it2) {
+ auto &mask = it2->priority_mask;
+ if (GetSize(mask) > i) {
+ mask.bits.erase(mask.bits.begin() + i);
+ }
+ }
+ return design_copy;
+ }
+ }
}
}
}
@@ -356,7 +377,7 @@ struct BugpointPass : public Pass {
if (wire->get_bool_attribute(ID::bugpoint_keep))
continue;
- if (wire->name.begins_with("$delete_wire"))
+ if (wire->name.begins_with("$delete_wire") || wire->name.begins_with("$auto$bugpoint"))
continue;
if (index++ == seed)
@@ -377,7 +398,7 @@ struct BugpointPass : public Pass {
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
- string yosys_cmd = "yosys", yosys_arg, grep;
+ string yosys_cmd = "yosys", yosys_arg, grep, runner;
bool fast = false, clean = false;
bool modules = false, ports = false, cells = false, connections = false, processes = false, assigns = false, updates = false, wires = false, has_part = false;
@@ -455,6 +476,14 @@ struct BugpointPass : public Pass {
has_part = true;
continue;
}
+ if (args[argidx] == "-runner" && argidx + 1 < args.size()) {
+ runner = args[++argidx];
+ if (runner.size() && runner.at(0) == '"') {
+ log_assert(runner.back() == '"');
+ runner = runner.substr(1, runner.size() - 2);
+ }
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -478,7 +507,7 @@ struct BugpointPass : public Pass {
log_cmd_error("This command only operates on fully selected designs!\n");
RTLIL::Design *crashing_design = clean_design(design, clean);
- if (run_yosys(crashing_design, yosys_cmd, yosys_arg))
+ if (run_yosys(crashing_design, runner, yosys_cmd, yosys_arg))
log_cmd_error("The provided script file or command and Yosys binary do not crash on this design!\n");
if (!check_logfile(grep))
log_cmd_error("The provided grep string is not found in the log file!\n");
@@ -495,12 +524,12 @@ struct BugpointPass : public Pass {
if (clean)
{
RTLIL::Design *testcase = clean_design(simplified);
- crashes = !run_yosys(testcase, yosys_cmd, yosys_arg);
+ crashes = !run_yosys(testcase, runner, yosys_cmd, yosys_arg);
delete testcase;
}
else
{
- crashes = !run_yosys(simplified, yosys_cmd, yosys_arg);
+ crashes = !run_yosys(simplified, runner, yosys_cmd, yosys_arg);
}
if (crashes && check_logfile(grep))
diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc
index 36febb98a..ee0f0a58f 100644
--- a/passes/cmds/check.cc
+++ b/passes/cmds/check.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -141,6 +141,14 @@ struct CheckPass : public Pass {
for (auto bit : sigmap(action.second))
if (bit.wire) used_wires.insert(bit);
}
+ for (auto memwr : sync->mem_write_actions) {
+ for (auto bit : sigmap(memwr.address))
+ if (bit.wire) used_wires.insert(bit);
+ for (auto bit : sigmap(memwr.data))
+ if (bit.wire) used_wires.insert(bit);
+ for (auto bit : sigmap(memwr.enable))
+ if (bit.wire) used_wires.insert(bit);
+ }
}
}
diff --git a/passes/cmds/chformal.cc b/passes/cmds/chformal.cc
index a1b3fbef7..d813a449c 100644
--- a/passes/cmds/chformal.cc
+++ b/passes/cmds/chformal.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/chtype.cc b/passes/cmds/chtype.cc
index b894f334c..6f9ca9a45 100644
--- a/passes/cmds/chtype.cc
+++ b/passes/cmds/chtype.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/clean_zerowidth.cc b/passes/cmds/clean_zerowidth.cc
new file mode 100644
index 000000000..bac6b1521
--- /dev/null
+++ b/passes/cmds/clean_zerowidth.cc
@@ -0,0 +1,210 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * 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/celltypes.h"
+#include "kernel/mem.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct CleanZeroWidthPass : public Pass {
+ CleanZeroWidthPass() : Pass("clean_zerowidth", "clean zero-width connections from the design") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" clean_zerowidth [selection]\n");
+ log("\n");
+ log("Fixes the selected cells and processes to contain no zero-width connections.\n");
+ log("Depending on the cell type, this may be implemented by removing the connection,\n");
+ log("widening it to 1-bit, or removing the cell altogether.\n");
+ log("\n");
+ }
+
+ void clean_case(RTLIL::CaseRule *cs)
+ {
+ std::vector<SigSig> new_actions;
+ for (auto &action : cs->actions)
+ if (GetSize(action.first) != 0)
+ new_actions.push_back(action);
+ std::swap(new_actions, cs->actions);
+ for (auto sw : cs->switches)
+ for (auto scs : sw->cases)
+ clean_case(scs);
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ CellTypes ct;
+ ct.setup();
+
+ for (auto module : design->selected_modules())
+ {
+ for (auto cell : module->selected_cells())
+ {
+ if (!ct.cell_known(cell->type)) {
+ // User-defined cell: just prune zero-width connections.
+ for (auto it: cell->connections()) {
+ if (GetSize(it.second) == 0) {
+ cell->unsetPort(it.first);
+ }
+ }
+ } else if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
+ // Coarse FF cells: remove if WIDTH == 0 (no outputs).
+ // This will also trigger on fine cells, so use the Q port
+ // width instead of actual WIDTH parameter.
+ if (GetSize(cell->getPort(ID::Q)) == 0) {
+ module->remove(cell);
+ }
+ } else if (cell->type.in(ID($pmux), ID($bmux), ID($demux))) {
+ // Remove altogether if WIDTH is 0, replace with
+ // a connection if S_WIDTH is 0.
+ if (cell->getParam(ID::WIDTH).as_int() == 0) {
+ module->remove(cell);
+ }
+ if (cell->getParam(ID::S_WIDTH).as_int() == 0) {
+ module->connect(cell->getPort(ID::Y), cell->getPort(ID::A));
+ module->remove(cell);
+ }
+ } else if (cell->type == ID($concat)) {
+ // If a concat has a zero-width input: replace with direct
+ // connection to the other input.
+ if (cell->getParam(ID::A_WIDTH).as_int() == 0) {
+ module->connect(cell->getPort(ID::Y), cell->getPort(ID::B));
+ module->remove(cell);
+ } else if (cell->getParam(ID::B_WIDTH).as_int() == 0) {
+ module->connect(cell->getPort(ID::Y), cell->getPort(ID::A));
+ module->remove(cell);
+ }
+ } else if (cell->type == ID($fsm)) {
+ // TODO: not supported
+ } else if (cell->is_mem_cell()) {
+ // Skip — will be handled below.
+ } else if (cell->type == ID($lut)) {
+ // Zero-width LUT is just a const driver.
+ if (cell->getParam(ID::WIDTH).as_int() == 0) {
+ module->connect(cell->getPort(ID::Y), cell->getParam(ID::LUT)[0]);
+ module->remove(cell);
+ }
+ } else if (cell->type == ID($sop)) {
+ // Zero-width SOP is just a const driver.
+ if (cell->getParam(ID::WIDTH).as_int() == 0) {
+ // The value is 1 iff DEPTH is non-0.
+ bool val = cell->getParam(ID::DEPTH).as_int() != 0;
+ module->connect(cell->getPort(ID::Y), val);
+ module->remove(cell);
+ }
+ } else if (cell->hasParam(ID::WIDTH)) {
+ // For cells with WIDTH parameter: remove if zero.
+ if (cell->getParam(ID::WIDTH).as_int() == 0) {
+ module->remove(cell);
+ }
+ } else if (cell->hasParam(ID::Y_WIDTH)) {
+ // For most operators: remove if Y width is 0, expand
+ // A and B to 1-bit if their width is 0.
+ if (cell->getParam(ID::Y_WIDTH).as_int() == 0) {
+ module->remove(cell);
+ } else if (cell->type == ID($macc)) {
+ // TODO: fixing zero-width A and B not supported.
+ } else {
+ if (cell->getParam(ID::A_WIDTH).as_int() == 0) {
+ cell->setPort(ID::A, State::S0);
+ cell->setParam(ID::A_WIDTH, 1);
+ }
+ if (cell->hasParam(ID::B_WIDTH) && cell->getParam(ID::B_WIDTH).as_int() == 0) {
+ cell->setPort(ID::B, State::S0);
+ cell->setParam(ID::B_WIDTH, 1);
+ }
+ }
+ }
+ }
+
+ // NOTE: Zero-width switch signals are left alone for processes, as there
+ // is no simple way of cleaning them up.
+ for (auto &it: module->processes) {
+ if (!design->selected(module, it.second))
+ continue;
+ clean_case(&it.second->root_case);
+ for (auto sync : it.second->syncs) {
+ std::vector<int> swizzle;
+ std::vector<RTLIL::MemWriteAction> new_memwr_actions;
+ for (int i = 0; i < GetSize(sync->mem_write_actions); i++) {
+ auto &memwr = sync->mem_write_actions[i];
+ if (GetSize(memwr.data) == 0)
+ continue;
+ if (GetSize(memwr.address) == 0)
+ memwr.address = State::S0;
+ Const priority_mask;
+ for (auto x : swizzle) {
+ priority_mask.bits.push_back(memwr.priority_mask.bits[x]);
+ }
+ memwr.priority_mask = priority_mask;
+ swizzle.push_back(i);
+ new_memwr_actions.push_back(memwr);
+ }
+ std::swap(new_memwr_actions, sync->mem_write_actions);
+ std::vector<SigSig> new_actions;
+ for (auto &action : sync->actions)
+ if (GetSize(action.first) != 0)
+ new_actions.push_back(action);
+ std::swap(new_actions, sync->actions);
+ }
+ }
+
+ for (auto &mem : Mem::get_selected_memories(module)) {
+ if (mem.width == 0) {
+ mem.remove();
+ continue;
+ }
+ for (auto &init : mem.inits) {
+ if (GetSize(init.addr) == 0) {
+ init.addr = State::S0;
+ }
+ }
+ for (auto &port : mem.rd_ports) {
+ if (GetSize(port.addr) == 0) {
+ port.addr = State::S0;
+ }
+ }
+ for (auto &port : mem.wr_ports) {
+ if (GetSize(port.addr) == 0) {
+ port.addr = State::S0;
+ }
+ }
+ mem.emit();
+ }
+
+ std::vector<SigSig> new_conns;
+ for (auto &conn : module->connections())
+ if (GetSize(conn.first) != 0)
+ new_conns.push_back(conn);
+ module->new_connections(new_conns);
+ }
+ }
+} CleanZeroWidthPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc
index 0cc6cbe52..1bd52aab2 100644
--- a/passes/cmds/connect.cc
+++ b/passes/cmds/connect.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -60,7 +60,7 @@ struct ConnectPass : public Pass {
log("Unconnect all existing drivers for the specified expression.\n");
log("\n");
log("\n");
- log(" connect [-nomap] -port <cell> <port> <expr>\n");
+ log(" connect [-nomap] [-assert] -port <cell> <port> <expr>\n");
log("\n");
log("Connect the specified cell port to the specified cell port.\n");
log("\n");
@@ -72,6 +72,9 @@ struct ConnectPass : public Pass {
log("The connect command operates in one module only. Either only one module must\n");
log("be selected or an active module must be set using the 'cd' command.\n");
log("\n");
+ log("The -assert option verifies that the connection already exists, instead of\n");
+ log("making it.\n");
+ log("\n");
log("This command does not operate on module with processes.\n");
log("\n");
}
@@ -88,7 +91,7 @@ struct ConnectPass : public Pass {
if (!module->processes.empty())
log_cmd_error("Found processes in selected module.\n");
- bool flag_nounset = false, flag_nomap = false;
+ bool flag_nounset = false, flag_nomap = false, flag_assert = false;
std::string set_lhs, set_rhs, unset_expr;
std::string port_cell, port_port, port_expr;
@@ -104,6 +107,10 @@ struct ConnectPass : public Pass {
flag_nomap = true;
continue;
}
+ if (arg == "-assert") {
+ flag_assert = true;
+ continue;
+ }
if (arg == "-set" && argidx+2 < args.size()) {
set_lhs = args[++argidx];
set_rhs = args[++argidx];
@@ -126,7 +133,7 @@ struct ConnectPass : public Pass {
if (!flag_nomap)
for (auto &it : module->connections()) {
std::vector<RTLIL::SigBit> lhs = it.first.to_sigbit_vector();
- std::vector<RTLIL::SigBit> rhs = it.first.to_sigbit_vector();
+ std::vector<RTLIL::SigBit> rhs = it.second.to_sigbit_vector();
for (size_t i = 0; i < lhs.size(); i++)
if (rhs[i].wire != nullptr)
sigmap.add(lhs[i], rhs[i]);
@@ -137,6 +144,9 @@ struct ConnectPass : public Pass {
if (!unset_expr.empty() || !port_cell.empty())
log_cmd_error("Can't use -set together with -unset and/or -port.\n");
+ if (flag_assert)
+ log_cmd_error("The -assert option is only supported with -port.\n");
+
RTLIL::SigSpec sig_lhs, sig_rhs;
if (!RTLIL::SigSpec::parse_sel(sig_lhs, design, module, set_lhs))
log_cmd_error("Failed to parse set lhs expression `%s'.\n", set_lhs.c_str());
@@ -157,6 +167,9 @@ struct ConnectPass : public Pass {
if (!port_cell.empty() || flag_nounset)
log_cmd_error("Can't use -unset together with -port and/or -nounset.\n");
+ if (flag_assert)
+ log_cmd_error("The -assert option is only supported with -port.\n");
+
RTLIL::SigSpec sig;
if (!RTLIL::SigSpec::parse_sel(sig, design, module, unset_expr))
log_cmd_error("Failed to parse unset expression `%s'.\n", unset_expr.c_str());
@@ -177,7 +190,14 @@ struct ConnectPass : public Pass {
if (!RTLIL::SigSpec::parse_sel(sig, design, module, port_expr))
log_cmd_error("Failed to parse port expression `%s'.\n", port_expr.c_str());
- module->cell(RTLIL::escape_id(port_cell))->setPort(RTLIL::escape_id(port_port), sigmap(sig));
+ if (!flag_assert) {
+ module->cell(RTLIL::escape_id(port_cell))->setPort(RTLIL::escape_id(port_port), sigmap(sig));
+ } else {
+ SigSpec cur = module->cell(RTLIL::escape_id(port_cell))->getPort(RTLIL::escape_id(port_port));
+ if (sigmap(sig) != sigmap(cur)) {
+ log_cmd_error("Expected connection not present: expected %s, found %s.\n", log_signal(sig), log_signal(cur));
+ }
+ }
}
else
log_cmd_error("Expected -set, -unset, or -port.\n");
diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc
index 9235dda2b..dbe23ccf1 100644
--- a/passes/cmds/connwrappers.cc
+++ b/passes/cmds/connwrappers.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/copy.cc b/passes/cmds/copy.cc
index c351065f3..e3fb3a0e6 100644
--- a/passes/cmds/copy.cc
+++ b/passes/cmds/copy.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc
index 0867e3b4f..1db3e2ca0 100644
--- a/passes/cmds/cover.cc
+++ b/passes/cmds/cover.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc
index 684fa37b0..e341f29d6 100644
--- a/passes/cmds/delete.cc
+++ b/passes/cmds/delete.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -90,7 +90,7 @@ struct DeletePass : public Pass {
pool<RTLIL::Wire*> delete_wires;
pool<RTLIL::Cell*> delete_cells;
- pool<RTLIL::IdString> delete_procs;
+ pool<RTLIL::Process*> delete_procs;
pool<RTLIL::IdString> delete_mems;
for (auto wire : module->selected_wires())
@@ -103,14 +103,14 @@ struct DeletePass : public Pass {
for (auto cell : module->cells()) {
if (design->selected(module, cell))
delete_cells.insert(cell);
- if (cell->type.in(ID($memrd), ID($memwr)) &&
+ if (cell->has_memid() &&
delete_mems.count(cell->parameters.at(ID::MEMID).decode_string()) != 0)
delete_cells.insert(cell);
}
for (auto &it : module->processes)
if (design->selected(module, it.second))
- delete_procs.insert(it.first);
+ delete_procs.insert(it.second);
for (auto &it : delete_mems) {
delete module->memories.at(it);
@@ -120,10 +120,8 @@ struct DeletePass : public Pass {
for (auto &it : delete_cells)
module->remove(it);
- for (auto &it : delete_procs) {
- delete module->processes.at(it);
- module->processes.erase(it);
- }
+ for (auto &it : delete_procs)
+ module->remove(it);
module->remove(delete_wires);
diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc
index 2d7ba1fef..169f7cc4a 100644
--- a/passes/cmds/design.cc
+++ b/passes/cmds/design.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/edgetypes.cc b/passes/cmds/edgetypes.cc
index 37c420400..5b53f50cc 100644
--- a/passes/cmds/edgetypes.cc
+++ b/passes/cmds/edgetypes.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/exec.cc b/passes/cmds/exec.cc
index 951fa53fc..f00629a02 100644
--- a/passes/cmds/exec.cc
+++ b/passes/cmds/exec.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 - 2020 Claire Wolf <claire@symbioticeda.com>
+ * Copyright (C) 2012 - 2020 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/glift.cc b/passes/cmds/glift.cc
new file mode 100644
index 000000000..b398c3e04
--- /dev/null
+++ b/passes/cmds/glift.cc
@@ -0,0 +1,599 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2020 Alberto Gonzalez <boqwxp@airmail.cc>
+ *
+ * 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/register.h"
+#include "kernel/rtlil.h"
+#include "kernel/utils.h"
+#include "kernel/log.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct GliftWorker {
+private:
+ bool is_top_module = false;
+ bool opt_create_precise_model = false, opt_create_imprecise_model = false, opt_create_instrumented_model = false;
+ bool opt_taintconstants = false, opt_keepoutputs = false, opt_simplecostmodel = false, opt_nocostmodel = false;
+ bool opt_instrumentmore = false;
+ std::vector<RTLIL::Wire *> new_taint_outputs;
+ std::vector<std::pair<RTLIL::SigSpec, RTLIL::IdString>> meta_mux_selects;
+ RTLIL::Module *module = nullptr;
+
+ const RTLIL::IdString cost_model_wire_name = ID(__glift_weight);
+ const RTLIL::IdString glift_attribute_name = ID(glift);
+
+
+ RTLIL::SigSpec get_corresponding_taint_signal(RTLIL::SigSpec sig) {
+ RTLIL::SigSpec ret;
+
+ //Get the connected wire for the cell port:
+ log_assert(sig.is_wire() || sig.is_fully_const());
+ log_assert(sig.is_wire() || sig.is_fully_const());
+
+ //Get a SigSpec for the corresponding taint signal for the cell port, creating one if necessary:
+ if (sig.is_wire()) {
+ RTLIL::Wire *w = module->wire(sig.as_wire()->name.str() + "_t");
+ if (w == nullptr) w = module->addWire(sig.as_wire()->name.str() + "_t", 1);
+ ret = w;
+ }
+ else if (sig.is_fully_const() && opt_taintconstants)
+ ret = RTLIL::State::S1;
+ else if (sig.is_fully_const())
+ ret = RTLIL::State::S0;
+ else
+ log_cmd_error("Cell port SigSpec has unexpected type.\n");
+
+ //Finally, if the cell port was a module input or output, make sure the corresponding taint signal is marked, too:
+ if(sig.is_wire() && sig.as_wire()->port_input)
+ ret.as_wire()->port_input = true;
+ if(sig.is_wire() && sig.as_wire()->port_output)
+ new_taint_outputs.push_back(ret.as_wire());
+
+ return ret;
+ }
+
+ void add_precise_GLIFT_logic(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_y_taint) {
+ //AKA AN2_SH2 or OR2_SH2
+ bool is_and = cell->type.in(ID($_AND_), ID($_NAND_));
+ RTLIL::SigSpec n_port_a = module->LogicNot(cell->name.str() + "_t_1_1", port_a, false, cell->get_src_attribute());
+ RTLIL::SigSpec n_port_b = module->LogicNot(cell->name.str() + "_t_1_2", port_b, false, cell->get_src_attribute());
+ auto subexpr1 = module->And(cell->name.str() + "_t_1_3", is_and? port_a : n_port_a, port_b_taint, false, cell->get_src_attribute());
+ auto subexpr2 = module->And(cell->name.str() + "_t_1_4", is_and? port_b : n_port_b, port_a_taint, false, cell->get_src_attribute());
+ auto subexpr3 = module->And(cell->name.str() + "_t_1_5", port_a_taint, port_b_taint, false, cell->get_src_attribute());
+ auto subexpr4 = module->Or(cell->name.str() + "_t_1_6", subexpr1, subexpr2, false, cell->get_src_attribute());
+ module->addOr(cell->name.str() + "_t_1_7", subexpr4, subexpr3, port_y_taint, false, cell->get_src_attribute());
+ }
+
+ void add_imprecise_GLIFT_logic_1(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_y_taint) {
+ //AKA AN2_SH3 or OR2_SH3
+ bool is_and = cell->type.in(ID($_AND_), ID($_NAND_));
+ RTLIL::SigSpec n_port_a = module->LogicNot(cell->name.str() + "_t_2_1", port_a, false, cell->get_src_attribute());
+ auto subexpr1 = module->And(cell->name.str() + "_t_2_2", is_and? port_b : n_port_a, is_and? port_a_taint : port_b_taint, false, cell->get_src_attribute());
+ module->addOr(cell->name.str() + "_t_2_3", is_and? port_b_taint : port_a_taint, subexpr1, port_y_taint, false, cell->get_src_attribute());
+ }
+
+ void add_imprecise_GLIFT_logic_2(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_y_taint) {
+ //AKA AN2_SH4 or OR2_SH4
+ bool is_and = cell->type.in(ID($_AND_), ID($_NAND_));
+ RTLIL::SigSpec n_port_b = module->LogicNot(cell->name.str() + "_t_3_1", port_b, false, cell->get_src_attribute());
+ auto subexpr1 = module->And(cell->name.str() + "_t_3_2", is_and? port_a : n_port_b, is_and? port_b_taint : port_a_taint, false, cell->get_src_attribute());
+ module->addOr(cell->name.str() + "_t_3_3", is_and? port_a_taint : port_b_taint, subexpr1, port_y_taint, false, cell->get_src_attribute());
+ }
+
+ void add_imprecise_GLIFT_logic_3(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_y_taint) {
+ //AKA AN2_SH5 or OR2_SH5 or XR2_SH2
+ module->addOr(cell->name.str() + "_t_4_1", port_a_taint, port_b_taint, port_y_taint, false, cell->get_src_attribute());
+ }
+
+ void add_imprecise_GLIFT_logic_4(RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_y_taint) {
+ module->connect(port_y_taint, port_a_taint);
+ }
+
+ void add_imprecise_GLIFT_logic_5(RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_y_taint) {
+ module->connect(port_y_taint, port_b_taint);
+ }
+
+ void add_imprecise_GLIFT_logic_6(RTLIL::SigSpec &port_y_taint) {
+ module->connect(port_y_taint, RTLIL::Const(1, 1));
+ }
+
+ void add_imprecise_GLIFT_logic_7(RTLIL::SigSpec &port_y_taint) {
+ module->connect(port_y_taint, RTLIL::Const(0, 1));
+ }
+
+ void add_precise_GLIFT_mux(const RTLIL::Cell *cell, RTLIL::SigSpec &port_a, RTLIL::SigSpec &port_a_taint, RTLIL::SigSpec &port_b, RTLIL::SigSpec &port_b_taint, RTLIL::SigSpec &port_s, RTLIL::SigSpec &port_s_taint, RTLIL::SigSpec &port_y_taint) {
+ //S&At | ~S&Bt | ~A&B&St | A&~B&St | At&St | Bt&St
+ RTLIL::SigSpec n_port_a = module->LogicNot(cell->name.str() + "_t_4_1", port_a, false, cell->get_src_attribute());
+ RTLIL::SigSpec n_port_b = module->LogicNot(cell->name.str() + "_t_4_2", port_b, false, cell->get_src_attribute());
+ RTLIL::SigSpec n_port_s = module->LogicNot(cell->name.str() + "_t_4_3", port_s, false, cell->get_src_attribute());
+ auto subexpr1 = module->And(cell->name.str() + "_t_4_4", port_s, port_a_taint, false, cell->get_src_attribute());
+ auto subexpr2 = module->And(cell->name.str() + "_t_4_5", n_port_s, port_b_taint, false, cell->get_src_attribute());
+ auto subexpr3 = module->And(cell->name.str() + "_t_4_6", n_port_a, port_b, false, cell->get_src_attribute());
+ auto subexpr4 = module->And(cell->name.str() + "_t_4_7", subexpr3, port_s_taint, false, cell->get_src_attribute());
+ auto subexpr5 = module->And(cell->name.str() + "_t_4_8", port_a, n_port_b, false, cell->get_src_attribute());
+ auto subexpr6 = module->And(cell->name.str() + "_t_4_9", subexpr5, port_s_taint, false, cell->get_src_attribute());
+ auto subexpr7 = module->And(cell->name.str() + "_t_4_10", port_a_taint, port_s_taint, false, cell->get_src_attribute());
+ auto subexpr8 = module->And(cell->name.str() + "_t_4_11", port_b_taint, port_s_taint, false, cell->get_src_attribute());
+ auto subexpr9 = module->Or(cell->name.str() + "_t_4_12", subexpr1, subexpr2, false, cell->get_src_attribute());
+ auto subexpr10 = module->Or(cell->name.str() + "_t_4_13", subexpr4, subexpr6, false, cell->get_src_attribute());
+ auto subexpr11 = module->Or(cell->name.str() + "_t_4_14", subexpr7, subexpr8, false, cell->get_src_attribute());
+ auto subexpr12 = module->Or(cell->name.str() + "_t_4_15", subexpr9, subexpr10, false, cell->get_src_attribute());
+ module->addOr(cell->name.str() + "_t_4_16", subexpr11, subexpr12, port_y_taint, false, cell->get_src_attribute());
+ }
+
+ RTLIL::SigSpec score_metamux_select(const RTLIL::SigSpec &metamux_select, const RTLIL::IdString celltype) {
+ log_assert(metamux_select.is_wire());
+
+ if (opt_simplecostmodel) {
+ //The complex model is an area model, so a lower score should mean smaller.
+ //In this case, a nonzero hole metamux select value means less logic.
+ //Thus we should invert the ReduceOr over the metamux_select signal.
+ RTLIL::SigSpec pmux_select = module->ReduceOr(metamux_select.as_wire()->name.str() + "_nonzero", metamux_select);
+ return module->Pmux(NEW_ID, RTLIL::Const(1), RTLIL::Const(0), pmux_select, metamux_select.as_wire()->get_src_attribute());
+ } else {
+ auto select_width = metamux_select.as_wire()->width;
+
+ std::vector<RTLIL::Const> costs;
+ if (celltype == ID($_AND_) || celltype == ID($_OR_)) {
+ costs = {5, 2, 2, 1, 0, 0, 0, 0};
+ log_assert(select_width == 2 || select_width == 3);
+ log_assert(opt_instrumentmore || select_width == 2);
+ log_assert(!opt_instrumentmore || select_width == 3);
+ }
+ else if (celltype == ID($_XOR_) || celltype == ID($_XNOR_)) {
+ costs = {1, 0, 0, 0};
+ log_assert(select_width == 2);
+ }
+
+ std::vector<RTLIL::SigSpec> next_pmux_y_ports, pmux_y_ports(costs.begin(), costs.begin() + exp2(select_width));
+ for (auto i = 0; pmux_y_ports.size() > 1; ++i) {
+ for (auto j = 0; j+1 < GetSize(pmux_y_ports); j += 2) {
+ next_pmux_y_ports.emplace_back(module->Pmux(stringf("%s_mux_%d_%d", metamux_select.as_wire()->name.c_str(), i, j), pmux_y_ports[j], pmux_y_ports[j+1], metamux_select[GetSize(metamux_select) - 1 - i], metamux_select.as_wire()->get_src_attribute()));
+ }
+ if (GetSize(pmux_y_ports) % 2 == 1)
+ next_pmux_y_ports.push_back(pmux_y_ports[GetSize(pmux_y_ports) - 1]);
+ pmux_y_ports.swap(next_pmux_y_ports);
+ next_pmux_y_ports.clear();
+ }
+
+ log_assert(pmux_y_ports.size() == 1);
+ return pmux_y_ports[0];
+ }
+ }
+
+ void create_glift_logic() {
+ if (module->get_bool_attribute(glift_attribute_name))
+ return;
+
+ std::vector<RTLIL::SigSig> connections(module->connections());
+
+ for(auto &cell : module->cells().to_vector()) {
+ if (!cell->type.in({ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_MUX_), ID($_NMUX_), ID($_NOT_), ID($anyconst), ID($allconst), ID($assume), ID($assert)}) && module->design->module(cell->type) == nullptr) {
+ log_cmd_error("Unsupported cell type \"%s\" found. Run `techmap` first.\n", cell->type.c_str());
+ }
+ if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_))) {
+ const unsigned int A = 0, B = 1, Y = 2;
+ const unsigned int NUM_PORTS = 3;
+ RTLIL::SigSpec ports[NUM_PORTS] = {cell->getPort(ID::A), cell->getPort(ID::B), cell->getPort(ID::Y)};
+ RTLIL::SigSpec port_taints[NUM_PORTS];
+
+ if (ports[A].size() != 1 || ports[B].size() != 1 || ports[Y].size() != 1)
+ log_cmd_error("Multi-bit signal found. Run `splitnets` first.\n");
+ for (unsigned int i = 0; i < NUM_PORTS; ++i)
+ port_taints[i] = get_corresponding_taint_signal(ports[i]);
+
+ if (opt_create_precise_model)
+ add_precise_GLIFT_logic(cell, ports[A], port_taints[A], ports[B], port_taints[B], port_taints[Y]);
+ else if (opt_create_imprecise_model)
+ add_imprecise_GLIFT_logic_3(cell, port_taints[A], port_taints[B], port_taints[Y]);
+ else if (opt_create_instrumented_model) {
+ std::vector<RTLIL::SigSpec> taint_version;
+ int num_versions = opt_instrumentmore? 8 : 4;
+
+ for (auto i = 1; i <= num_versions; ++i)
+ taint_version.emplace_back(RTLIL::SigSpec(module->addWire(stringf("%s_y%d", cell->name.c_str(), i), 1)));
+
+ for (auto i = 0; i < num_versions; ++i) {
+ switch(i) {
+ case 0: add_precise_GLIFT_logic(cell, ports[A], port_taints[A], ports[B], port_taints[B], taint_version[i]);
+ break;
+ case 1: add_imprecise_GLIFT_logic_1(cell, ports[A], port_taints[A], ports[B], port_taints[B], taint_version[i]);
+ break;
+ case 2: add_imprecise_GLIFT_logic_2(cell, ports[A], port_taints[A], ports[B], port_taints[B], taint_version[i]);
+ break;
+ case 3: add_imprecise_GLIFT_logic_3(cell, port_taints[A], port_taints[B], taint_version[i]);
+ break;
+ case 4: add_imprecise_GLIFT_logic_4(port_taints[A], taint_version[i]);
+ break;
+ case 5: add_imprecise_GLIFT_logic_5(port_taints[B], taint_version[i]);
+ break;
+ case 6: add_imprecise_GLIFT_logic_6(taint_version[i]);
+ break;
+ case 7: add_imprecise_GLIFT_logic_7(taint_version[i]);
+ break;
+ default: log_assert(false);
+ }
+ }
+
+ auto select_width = log2(num_versions);
+ log_assert(exp2(select_width) == num_versions);
+ RTLIL::SigSpec meta_mux_select(module->addWire(cell->name.str() + "_sel", select_width));
+ meta_mux_selects.push_back(make_pair(meta_mux_select, cell->type));
+ module->connect(meta_mux_select, module->Anyconst(cell->name.str() + "_hole", select_width, cell->get_src_attribute()));
+
+ std::vector<RTLIL::SigSpec> next_meta_mux_y_ports, meta_mux_y_ports(taint_version);
+ for (auto i = 0; meta_mux_y_ports.size() > 1; ++i) {
+ for (auto j = 0; j+1 < GetSize(meta_mux_y_ports); j += 2) {
+ next_meta_mux_y_ports.emplace_back(module->Mux(stringf("%s_mux_%d_%d", cell->name.c_str(), i, j), meta_mux_y_ports[j], meta_mux_y_ports[j+1], meta_mux_select[GetSize(meta_mux_select) - 1 - i]));
+ }
+ if (GetSize(meta_mux_y_ports) % 2 == 1)
+ next_meta_mux_y_ports.push_back(meta_mux_y_ports[GetSize(meta_mux_y_ports) - 1]);
+ meta_mux_y_ports.swap(next_meta_mux_y_ports);
+ next_meta_mux_y_ports.clear();
+ }
+ log_assert(meta_mux_y_ports.size() == 1);
+ module->connect(port_taints[Y], meta_mux_y_ports[0]);
+ }
+ else log_cmd_error("This is a bug (1).\n");
+ }
+ else if (cell->type.in(ID($_XOR_), ID($_XNOR_))) {
+ const unsigned int A = 0, B = 1, Y = 2;
+ const unsigned int NUM_PORTS = 3;
+ RTLIL::SigSpec ports[NUM_PORTS] = {cell->getPort(ID::A), cell->getPort(ID::B), cell->getPort(ID::Y)};
+ RTLIL::SigSpec port_taints[NUM_PORTS];
+
+ if (ports[A].size() != 1 || ports[B].size() != 1 || ports[Y].size() != 1)
+ log_cmd_error("Multi-bit signal found. Run `splitnets` first.\n");
+ for (unsigned int i = 0; i < NUM_PORTS; ++i)
+ port_taints[i] = get_corresponding_taint_signal(ports[i]);
+
+ if (opt_create_precise_model || opt_create_imprecise_model)
+ add_imprecise_GLIFT_logic_3(cell, port_taints[A], port_taints[B], port_taints[Y]);
+ else if (opt_create_instrumented_model) {
+ std::vector<RTLIL::SigSpec> taint_version;
+ int num_versions = 4;
+ auto select_width = log2(num_versions);
+ log_assert(exp2(select_width) == num_versions);
+
+ for (auto i = 1; i <= num_versions; ++i)
+ taint_version.emplace_back(RTLIL::SigSpec(module->addWire(stringf("%s_y%d", cell->name.c_str(), i), 1)));
+
+ for (auto i = 0; i < num_versions; ++i) {
+ switch(i) {
+ case 0: add_imprecise_GLIFT_logic_3(cell, port_taints[A], port_taints[B], taint_version[i]);
+ break;
+ case 1: add_imprecise_GLIFT_logic_4(port_taints[A], taint_version[i]);
+ break;
+ case 2: add_imprecise_GLIFT_logic_5(port_taints[B], taint_version[i]);
+ break;
+ case 3: add_imprecise_GLIFT_logic_6(taint_version[i]);
+ break;
+ default: log_assert(false);
+ }
+ }
+
+ RTLIL::SigSpec meta_mux_select(module->addWire(cell->name.str() + "_sel", select_width));
+ meta_mux_selects.push_back(make_pair(meta_mux_select, cell->type));
+ module->connect(meta_mux_select, module->Anyconst(cell->name.str() + "_hole", select_width, cell->get_src_attribute()));
+
+ std::vector<RTLIL::SigSpec> next_meta_mux_y_ports, meta_mux_y_ports(taint_version);
+ for (auto i = 0; meta_mux_y_ports.size() > 1; ++i) {
+ for (auto j = 0; j+1 < GetSize(meta_mux_y_ports); j += 2) {
+ next_meta_mux_y_ports.emplace_back(module->Mux(stringf("%s_mux_%d_%d", cell->name.c_str(), i, j), meta_mux_y_ports[j], meta_mux_y_ports[j+1], meta_mux_select[GetSize(meta_mux_select) - 1 - i]));
+ }
+ if (GetSize(meta_mux_y_ports) % 2 == 1)
+ next_meta_mux_y_ports.push_back(meta_mux_y_ports[GetSize(meta_mux_y_ports) - 1]);
+ meta_mux_y_ports.swap(next_meta_mux_y_ports);
+ next_meta_mux_y_ports.clear();
+ }
+ log_assert(meta_mux_y_ports.size() == 1);
+ module->connect(port_taints[Y], meta_mux_y_ports[0]);
+ }
+ else log_cmd_error("This is a bug (2).\n");
+
+ }
+ else if (cell->type.in(ID($_MUX_), ID($_NMUX_))) {
+ const unsigned int A = 0, B = 1, S = 2, Y = 3;
+ const unsigned int NUM_PORTS = 4;
+ RTLIL::SigSpec ports[NUM_PORTS] = {cell->getPort(ID::A), cell->getPort(ID::B), cell->getPort(ID::S), cell->getPort(ID::Y)};
+ RTLIL::SigSpec port_taints[NUM_PORTS];
+
+ if (ports[A].size() != 1 || ports[B].size() != 1 || ports[S].size() != 1 || ports[Y].size() != 1)
+ log_cmd_error("Multi-bit signal found. Run `splitnets` first.\n");
+ for (unsigned int i = 0; i < NUM_PORTS; ++i)
+ port_taints[i] = get_corresponding_taint_signal(ports[i]);
+
+ add_precise_GLIFT_mux(cell, ports[A], port_taints[A], ports[B], port_taints[B], ports[S], port_taints[S], port_taints[Y]);
+ }
+ else if (cell->type.in(ID($_NOT_))) {
+ const unsigned int A = 0, Y = 1;
+ const unsigned int NUM_PORTS = 2;
+ RTLIL::SigSpec ports[NUM_PORTS] = {cell->getPort(ID::A), cell->getPort(ID::Y)};
+ RTLIL::SigSpec port_taints[NUM_PORTS];
+
+ if (ports[A].size() != 1 || ports[Y].size() != 1)
+ log_cmd_error("Multi-bit signal found. Run `splitnets` first.\n");
+ for (unsigned int i = 0; i < NUM_PORTS; ++i)
+ port_taints[i] = get_corresponding_taint_signal(ports[i]);
+
+ if (cell->type == ID($_NOT_)) {
+ module->connect(port_taints[Y], port_taints[A]);
+ }
+ else log_cmd_error("This is a bug (3).\n");
+ }
+ else if (module->design->module(cell->type) != nullptr) {
+ //User cell type
+ //This function is called on modules according to topological order, so we do not need to
+ //recurse to GLIFT model the child module. However, we need to augment the ports list
+ //with taint signals and connect the new ports to the corresponding taint signals.
+ RTLIL::Module *cell_module_def = module->design->module(cell->type);
+ dict<RTLIL::IdString, RTLIL::SigSpec> orig_ports = cell->connections();
+ log("Adding cell %s\n", cell_module_def->name.c_str());
+ for (auto &it : orig_ports) {
+ RTLIL::SigSpec port = it.second;
+ RTLIL::SigSpec port_taint = get_corresponding_taint_signal(port);
+
+ log_assert(port_taint.is_wire());
+ log_assert(std::find(cell_module_def->ports.begin(), cell_module_def->ports.end(), port_taint.as_wire()->name) != cell_module_def->ports.end());
+ cell->setPort(port_taint.as_wire()->name, port_taint);
+ }
+ }
+ else log_cmd_error("This is a bug (4).\n");
+ } //end foreach cell in cells
+
+ for (auto &conn : connections) {
+ RTLIL::SigSpec first = get_corresponding_taint_signal(conn.first);
+ RTLIL::SigSpec second = get_corresponding_taint_signal(conn.second);
+
+ module->connect(first, second);
+
+ if(conn.second.is_wire() && conn.second.as_wire()->port_input)
+ second.as_wire()->port_input = true;
+ if(conn.first.is_wire() && conn.first.as_wire()->port_output)
+ new_taint_outputs.push_back(first.as_wire());
+ } //end foreach conn in connections
+
+ //Create a rough model of area by summing the (potentially simplified) "weight" score of each meta-mux select:
+ if (!opt_nocostmodel) {
+ std::vector<RTLIL::SigSpec> meta_mux_select_sums;
+ std::vector<RTLIL::SigSpec> meta_mux_select_sums_buf;
+ for (auto &it : meta_mux_selects) {
+ meta_mux_select_sums.emplace_back(score_metamux_select(it.first, it.second));
+ }
+ for (unsigned int i = 0; meta_mux_select_sums.size() > 1; ) {
+ meta_mux_select_sums_buf.clear();
+ for (i = 0; i + 1 < meta_mux_select_sums.size(); i += 2) {
+ meta_mux_select_sums_buf.push_back(module->Add(meta_mux_select_sums[i].as_wire()->name.str() + "_add", meta_mux_select_sums[i], meta_mux_select_sums[i+1], false));
+ }
+ if (meta_mux_select_sums.size() % 2 == 1)
+ meta_mux_select_sums_buf.push_back(meta_mux_select_sums[meta_mux_select_sums.size()-1]);
+ meta_mux_select_sums.swap(meta_mux_select_sums_buf);
+ }
+ if (meta_mux_select_sums.size() > 0) {
+ meta_mux_select_sums[0].as_wire()->set_bool_attribute("\\minimize");
+ meta_mux_select_sums[0].as_wire()->set_bool_attribute("\\keep");
+ module->rename(meta_mux_select_sums[0].as_wire(), cost_model_wire_name);
+ }
+ }
+
+ //Mark new module outputs:
+ for (auto &port_name : module->ports) {
+ RTLIL::Wire *port = module->wire(port_name);
+ log_assert(port != nullptr);
+ if (is_top_module && port->port_output && !opt_keepoutputs)
+ port->port_output = false;
+ }
+ for (auto &output : new_taint_outputs)
+ output->port_output = true;
+ module->fixup_ports(); //we have some new taint signals in the module interface
+ module->set_bool_attribute(glift_attribute_name, true);
+ }
+
+public:
+ GliftWorker(RTLIL::Module *_module, bool _is_top_module, bool _opt_create_precise_model, bool _opt_create_imprecise_model, bool _opt_create_instrumented_model, bool _opt_taintconstants, bool _opt_keepoutputs, bool _opt_simplecostmodel, bool _opt_nocostmodel, bool _opt_instrumentmore) {
+ module = _module;
+ is_top_module = _is_top_module;
+ opt_create_precise_model = _opt_create_precise_model;
+ opt_create_imprecise_model = _opt_create_imprecise_model;
+ opt_create_instrumented_model = _opt_create_instrumented_model;
+ opt_taintconstants = _opt_taintconstants;
+ opt_keepoutputs = _opt_keepoutputs;
+ opt_simplecostmodel = _opt_simplecostmodel;
+ opt_nocostmodel = _opt_nocostmodel;
+ opt_instrumentmore = _opt_instrumentmore;
+
+ create_glift_logic();
+ }
+};
+
+struct GliftPass : public Pass {
+ GliftPass() : Pass("glift", "create GLIFT models and optimization problems") {}
+
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" glift <command> [options] [selection]\n");
+ log("\n");
+ log("Augments the current or specified module with gate-level information flow tracking\n");
+ log("(GLIFT) logic using the \"constructive mapping\" approach. Also can set up QBF-SAT\n");
+ log("optimization problems in order to optimize GLIFT models or trade off precision and\n");
+ log("complexity.\n");
+ log("\n");
+ log("\n");
+ log("Commands:\n");
+ log("\n");
+ log(" -create-precise-model\n");
+ log(" Replaces the current or specified module with one that has corresponding \"taint\"\n");
+ log(" inputs, outputs, and internal nets along with precise taint tracking logic.\n");
+ log(" For example, precise taint tracking logic for an AND gate is:\n");
+ log("\n");
+ log(" y_t = a & b_t | b & a_t | a_t & b_t\n");
+ log("\n");
+ log("\n");
+ log(" -create-imprecise-model\n");
+ log(" Replaces the current or specified module with one that has corresponding \"taint\"\n");
+ log(" inputs, outputs, and internal nets along with imprecise \"All OR\" taint tracking\n");
+ log(" logic:\n");
+ log("\n");
+ log(" y_t = a_t | b_t\n");
+ log("\n");
+ log("\n");
+ log(" -create-instrumented-model\n");
+ log(" Replaces the current or specified module with one that has corresponding \"taint\"\n");
+ log(" inputs, outputs, and internal nets along with 4 varying-precision versions of taint\n");
+ log(" tracking logic. Which version of taint tracking logic is used for a given gate is\n");
+ log(" determined by a MUX selected by an $anyconst cell. By default, unless the\n");
+ log(" `-no-cost-model` option is provided, an additional wire named `__glift_weight` with\n");
+ log(" the `keep` and `minimize` attributes is added to the module along with pmuxes and\n");
+ log(" adders to calculate a rough estimate of the number of logic gates in the GLIFT model\n");
+ log(" given an assignment for the $anyconst cells. The four versions of taint tracking logic\n");
+ log(" for an AND gate are:");
+ log("\n");
+ log(" y_t = a & b_t | b & a_t | a_t & b_t (like `-create-precise-model`)\n");
+ log(" y_t = a_t | a & b_t\n");
+ log(" y_t = b_t | b & a_t\n");
+ log(" y_t = a_t | b_t (like `-create-imprecise-model`)\n");
+ log("\n");
+ log("\n");
+ log("Options:\n");
+ log("\n");
+ log(" -taint-constants\n");
+ log(" Constant values in the design are labeled as tainted.\n");
+ log(" (default: label constants as un-tainted)\n");
+ log("\n");
+ log(" -keep-outputs\n");
+ log(" Do not remove module outputs. Taint tracking outputs will appear in the module ports\n");
+ log(" alongside the orignal outputs.\n");
+ log(" (default: original module outputs are removed)\n");
+ log("\n");
+ log(" -simple-cost-model\n");
+ log(" Do not model logic area. Instead model the number of non-zero assignments to $anyconsts.\n");
+ log(" Taint tracking logic versions vary in their size, but all reduced-precision versions are\n");
+ log(" significantly smaller than the fully-precise version. A non-zero $anyconst assignment means\n");
+ log(" that reduced-precision taint tracking logic was chosen for some gate.\n");
+ log(" Only applicable in combination with `-create-instrumented-model`.\n");
+ log(" (default: use a complex model and give that wire the \"keep\" and \"minimize\" attributes)\n");
+ log("\n");
+ log(" -no-cost-model\n");
+ log(" Do not model taint tracking logic area and do not create a `__glift_weight` wire.\n");
+ log(" Only applicable in combination with `-create-instrumented-model`.\n");
+ log(" (default: model area and give that wire the \"keep\" and \"minimize\" attributes)\n");
+ log("\n");
+ log(" -instrument-more\n");
+ log(" Allow choice from more versions of (even simpler) taint tracking logic. A total\n");
+ log(" of 8 versions of taint tracking logic will be added per gate, including the 4\n");
+ log(" versions from `-create-instrumented-model` and these additional versions:\n");
+ log("\n");
+ log(" y_t = a_t\n");
+ log(" y_t = b_t\n");
+ log(" y_t = 1\n");
+ log(" y_t = 0\n");
+ log("\n");
+ log(" Only applicable in combination with `-create-instrumented-model`.\n");
+ log(" (default: do not add more versions of taint tracking logic.\n");
+ log("\n");
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ bool opt_create_precise_model = false, opt_create_imprecise_model = false, opt_create_instrumented_model = false;
+ bool opt_taintconstants = false, opt_keepoutputs = false, opt_simplecostmodel = false, opt_nocostmodel = false;
+ bool opt_instrumentmore = false;
+ log_header(design, "Executing GLIFT pass (creating and manipulating GLIFT models).\n");
+ std::vector<std::string>::size_type argidx;
+
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-create-precise-model") {
+ opt_create_precise_model = true;
+ continue;
+ }
+ if (args[argidx] == "-create-imprecise-model") {
+ opt_create_imprecise_model = true;
+ continue;
+ }
+ if (args[argidx] == "-create-instrumented-model") {
+ opt_create_instrumented_model = true;
+ continue;
+ }
+ if (args[argidx] == "-taint-constants") {
+ opt_taintconstants = true;
+ continue;
+ }
+ if (args[argidx] == "-keep-outputs") {
+ opt_keepoutputs = true;
+ continue;
+ }
+ if (args[argidx] == "-simple-cost-model") {
+ opt_simplecostmodel = true;
+ continue;
+ }
+ if (args[argidx] == "-no-cost-model") {
+ opt_nocostmodel = true;
+ continue;
+ }
+ if (args[argidx] == "-instrument-more") {
+ opt_instrumentmore = true;
+ continue;
+ }
+ break;
+ }
+ if(!opt_create_precise_model && !opt_create_imprecise_model && !opt_create_instrumented_model)
+ log_cmd_error("No command provided. See help for usage.\n");
+ if(static_cast<int>(opt_create_precise_model) + static_cast<int>(opt_create_imprecise_model) + static_cast<int>(opt_create_instrumented_model) != 1)
+ log_cmd_error("Only one command may be specified. See help for usage.\n");
+ if(opt_simplecostmodel && opt_nocostmodel)
+ log_cmd_error("Only one of `-simple-cost-model` and `-no-cost-model` may be specified. See help for usage.\n");
+ if((opt_simplecostmodel || opt_nocostmodel) && !opt_create_instrumented_model)
+ log_cmd_error("Options `-simple-cost-model` and `-no-cost-model` may only be used with `-create-instrumented-model`. See help for usage.\n");
+ extra_args(args, argidx, design);
+
+ if (GetSize(design->selected_modules()) == 0)
+ log_cmd_error("Can't operate on an empty selection!\n");
+
+ TopoSort<RTLIL::Module*, IdString::compare_ptr_by_name<RTLIL::Module>> topo_modules; //cribbed from passes/techmap/flatten.cc
+ auto worklist = design->selected_modules();
+ pool<RTLIL::IdString> non_top_modules;
+ while (!worklist.empty()) {
+ RTLIL::Module *module = *(worklist.begin());
+ worklist.erase(worklist.begin());
+ topo_modules.node(module);
+
+ for (auto cell : module->selected_cells()) {
+ RTLIL::Module *tpl = design->module(cell->type);
+ if (tpl != nullptr) {
+ if (topo_modules.database.count(tpl) == 0)
+ worklist.push_back(tpl);
+ topo_modules.edge(tpl, module);
+ non_top_modules.insert(cell->type);
+ }
+ }
+ }
+
+ if (!topo_modules.sort())
+ log_cmd_error("Cannot handle recursive module instantiations.\n");
+
+ for (auto i = 0; i < GetSize(topo_modules.sorted); ++i) {
+ RTLIL::Module *module = topo_modules.sorted[i];
+ GliftWorker(module, !non_top_modules[module->name], opt_create_precise_model, opt_create_imprecise_model, opt_create_instrumented_model, opt_taintconstants, opt_keepoutputs, opt_simplecostmodel, opt_nocostmodel, opt_instrumentmore);
+ }
+ }
+} GliftPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/logcmd.cc b/passes/cmds/logcmd.cc
index 12c43ecec..f1702400d 100644
--- a/passes/cmds/logcmd.cc
+++ b/passes/cmds/logcmd.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/cmds/logger.cc b/passes/cmds/logger.cc
index 6a9ed6036..ec92f1d01 100644
--- a/passes/cmds/logger.cc
+++ b/passes/cmds/logger.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2020 Miodrag Milanovic <clifford@clifford.at>
+ * Copyright (C) 2020 Miodrag Milanovic <micko@yosyshq.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
@@ -64,6 +64,11 @@ struct LoggerPass : public Pass {
log(" -expect-no-warnings\n");
log(" gives error in case there is at least one warning that is not expected.\n");
log("\n");
+ log(" -check-expected\n");
+ log(" verifies that the patterns previously set up by -expect have actually\n");
+ log(" been met, then clears the expected log list. If this is not called\n");
+ log(" manually, the check will happen at yosys exist time instead.\n");
+ log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design * design) override
@@ -176,6 +181,10 @@ struct LoggerPass : public Pass {
log_expect_no_warnings = true;
continue;
}
+ if (args[argidx] == "-check-expected") {
+ log_check_expected();
+ continue;
+ }
break;
}
extra_args(args, argidx, design, false);
diff --git a/passes/cmds/ltp.cc b/passes/cmds/ltp.cc
index 39ec432c2..22bdaab44 100644
--- a/passes/cmds/ltp.cc
+++ b/passes/cmds/ltp.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc
index a94769bcd..3a1ae2850 100644
--- a/passes/cmds/plugin.cc
+++ b/passes/cmds/plugin.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/portlist.cc b/passes/cmds/portlist.cc
index 97f4bfd99..03048422d 100644
--- a/passes/cmds/portlist.cc
+++ b/passes/cmds/portlist.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/qwp.cc b/passes/cmds/qwp.cc
index cf0f6d0de..2da612441 100644
--- a/passes/cmds/qwp.cc
+++ b/passes/cmds/qwp.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc
index f8fe715c8..1d08fc514 100644
--- a/passes/cmds/rename.cc
+++ b/passes/cmds/rename.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/scatter.cc b/passes/cmds/scatter.cc
index a70dd3086..017600a46 100644
--- a/passes/cmds/scatter.cc
+++ b/passes/cmds/scatter.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/scc.cc b/passes/cmds/scc.cc
index 7aa9a484f..81881832c 100644
--- a/passes/cmds/scc.cc
+++ b/passes/cmds/scc.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/scratchpad.cc b/passes/cmds/scratchpad.cc
index 9369f5312..015eb97e7 100644
--- a/passes/cmds/scratchpad.cc
+++ b/passes/cmds/scratchpad.cc
@@ -1,8 +1,8 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * 2019 Nina Engelhardt <nak@symbioticeda.com>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
+ * 2019 N. Engelhardt <nak@yosyshq.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
diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc
index b4f3994a2..bb7b78cfe 100644
--- a/passes/cmds/select.cc
+++ b/passes/cmds/select.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc
index 3a94209d4..710fa9ab4 100644
--- a/passes/cmds/setattr.cc
+++ b/passes/cmds/setattr.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc
index cf8d76619..a078b0b1c 100644
--- a/passes/cmds/setundef.cc
+++ b/passes/cmds/setundef.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index 0c96f8c5d..8f9824f9b 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -239,6 +239,19 @@ struct ShowWorker
int idx = single_idx_count++;
for (int rep, i = int(sig.chunks().size())-1; i >= 0; i -= rep) {
const RTLIL::SigChunk &c = sig.chunks().at(i);
+ int cl, cr;
+ if (c.wire) {
+ if (c.wire->upto) {
+ cr = c.wire->start_offset + (c.wire->width - c.offset - 1);
+ cl = cr - (c.width - 1);
+ } else {
+ cr = c.wire->start_offset + c.offset;
+ cl = cr + c.width - 1;
+ }
+ } else {
+ cl = c.offset + c.width - 1;
+ cr = c.offset;
+ }
if (!driver && c.wire == nullptr) {
RTLIL::State s1 = c.data.front();
for (auto s2 : c.data)
@@ -254,7 +267,7 @@ struct ShowWorker
std::string repinfo = rep > 1 ? stringf("%dx ", rep) : "";
if (driver) {
log_assert(!net.empty());
- label_string += stringf("<s%d> %d:%d - %s%d:%d |", i, pos, pos-c.width+1, repinfo.c_str(), c.offset+c.width-1, c.offset);
+ label_string += stringf("<s%d> %d:%d - %s%d:%d |", i, pos, pos-c.width+1, repinfo.c_str(), cl, cr);
net_conn_map[net].in.insert(stringf("x%d:s%d", idx, i));
net_conn_map[net].bits = rep*c.width;
net_conn_map[net].color = nextColor(c, net_conn_map[net].color);
@@ -268,7 +281,7 @@ struct ShowWorker
c.data.front() == State::Sz ? 'Z' : '?',
pos, pos-rep*c.width+1);
} else {
- label_string += stringf("<s%d> %s%d:%d - %d:%d |", i, repinfo.c_str(), c.offset+c.width-1, c.offset, pos, pos-rep*c.width+1);
+ label_string += stringf("<s%d> %s%d:%d - %d:%d |", i, repinfo.c_str(), cl, cr, pos, pos-rep*c.width+1);
net_conn_map[net].out.insert(stringf("x%d:s%d", idx, i));
net_conn_map[net].bits = rep*c.width;
net_conn_map[net].color = nextColor(c, net_conn_map[net].color);
@@ -339,6 +352,11 @@ struct ShowWorker
{
input_signals.insert(obj->signal);
collect_proc_signals(obj->actions, input_signals, output_signals);
+ for (auto it : obj->mem_write_actions) {
+ input_signals.insert(it.address);
+ input_signals.insert(it.data);
+ input_signals.insert(it.enable);
+ }
}
void collect_proc_signals(RTLIL::Process *obj, std::set<RTLIL::SigSpec> &input_signals, std::set<RTLIL::SigSpec> &output_signals)
@@ -648,7 +666,7 @@ struct ShowPass : public Pass {
log(" (including inout ports) are on the right side.\n");
log("\n");
log(" -pause\n");
- log(" wait for the use to press enter to before returning\n");
+ log(" wait for the user to press enter to before returning\n");
log("\n");
log(" -enum\n");
log(" enumerate objects with internal ($-prefixed) names\n");
diff --git a/passes/cmds/splice.cc b/passes/cmds/splice.cc
index 0f63b91c5..4ad0d2b25 100644
--- a/passes/cmds/splice.cc
+++ b/passes/cmds/splice.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc
index fff8a0d3e..927cefca3 100644
--- a/passes/cmds/splitnets.cc
+++ b/passes/cmds/splitnets.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/cmds/sta.cc b/passes/cmds/sta.cc
new file mode 100644
index 000000000..13e1ee13c
--- /dev/null
+++ b/passes/cmds/sta.cc
@@ -0,0 +1,312 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * (C) 2019 Eddie Hung <eddie@fpgeh.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 "kernel/yosys.h"
+#include "kernel/sigtools.h"
+#include "kernel/timinginfo.h"
+#include <deque>
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct StaWorker
+{
+ Design *design;
+ Module *module;
+ SigMap sigmap;
+
+ struct t_data {
+ Cell* driver;
+ IdString dst_port, src_port;
+ vector<tuple<SigBit,int,IdString>> fanouts;
+ SigBit backtrack;
+ t_data() : driver(nullptr) {}
+ };
+ dict<SigBit, t_data> data;
+ std::deque<SigBit> queue;
+ struct t_endpoint {
+ Cell *sink;
+ IdString port;
+ int required;
+ t_endpoint() : sink(nullptr), required(0) {}
+ };
+ dict<SigBit, t_endpoint> endpoints;
+
+ int maxarrival;
+ SigBit maxbit;
+
+ pool<SigBit> driven;
+
+ StaWorker(RTLIL::Module *module) : design(module->design), module(module), sigmap(module), maxarrival(0)
+ {
+ TimingInfo timing;
+
+ for (auto cell : module->cells())
+ {
+ Module *inst_module = design->module(cell->type);
+ if (!inst_module) {
+ log_warning("Cell type '%s' not recognised! Ignoring.\n", log_id(cell->type));
+ continue;
+ }
+
+ if (!inst_module->get_blackbox_attribute()) {
+ log_warning("Cell type '%s' is not a black- nor white-box! Ignoring.\n", log_id(cell->type));
+ continue;
+ }
+
+ IdString derived_type = inst_module->derive(design, cell->parameters);
+ inst_module = design->module(derived_type);
+ log_assert(inst_module);
+
+ if (!timing.count(derived_type)) {
+ auto &t = timing.setup_module(inst_module);
+ if (t.has_inputs && t.comb.empty() && t.arrival.empty() && t.required.empty())
+ log_warning("Module '%s' has no timing arcs!\n", log_id(cell->type));
+ }
+
+ auto &t = timing.at(derived_type);
+ if (t.comb.empty() && t.arrival.empty() && t.required.empty())
+ continue;
+
+ pool<std::pair<SigBit,TimingInfo::NameBit>> src_bits, dst_bits;
+
+ for (auto &conn : cell->connections()) {
+ auto rhs = sigmap(conn.second);
+ for (auto i = 0; i < GetSize(rhs); i++) {
+ const auto &bit = rhs[i];
+ if (!bit.wire)
+ continue;
+ TimingInfo::NameBit namebit(conn.first,i);
+ if (cell->input(conn.first)) {
+ src_bits.insert(std::make_pair(bit,namebit));
+
+ auto it = t.required.find(namebit);
+ if (it == t.required.end())
+ continue;
+ auto r = endpoints.insert(bit);
+ if (r.second || r.first->second.required < it->second.first) {
+ r.first->second.sink = cell;
+ r.first->second.port = conn.first;
+ r.first->second.required = it->second.first;
+ }
+ }
+ if (cell->output(conn.first)) {
+ dst_bits.insert(std::make_pair(bit,namebit));
+ auto &d = data[bit];
+ d.driver = cell;
+ d.dst_port = conn.first;
+ driven.insert(bit);
+
+ auto it = t.arrival.find(namebit);
+ if (it == t.arrival.end())
+ continue;
+ const auto &s = it->second.second;
+ if (cell->hasPort(s.name)) {
+ auto s_bit = sigmap(cell->getPort(s.name)[s.offset]);
+ if (s_bit.wire)
+ data[s_bit].fanouts.emplace_back(bit,it->second.first,s.name);
+ }
+ }
+ }
+ }
+
+ for (const auto &s : src_bits)
+ for (const auto &d : dst_bits) {
+ auto it = t.comb.find(TimingInfo::BitBit(s.second,d.second));
+ if (it == t.comb.end())
+ continue;
+ data[s.first].fanouts.emplace_back(d.first,it->second,s.second.name);
+ }
+ }
+
+ for (auto port_name : module->ports) {
+ auto wire = module->wire(port_name);
+ if (wire->port_input) {
+ for (const auto &b : sigmap(wire)) {
+ queue.emplace_back(b);
+ driven.insert(b);
+ }
+ // All primary inputs to arrive at time zero
+ wire->set_intvec_attribute(ID::sta_arrival, std::vector<int>(GetSize(wire), 0));
+ }
+ if (wire->port_output)
+ for (const auto &b : sigmap(wire))
+ if (b.wire)
+ endpoints.insert(b);
+ }
+ }
+
+ void run()
+ {
+ while (!queue.empty()) {
+ auto b = queue.front();
+ queue.pop_front();
+ auto it = data.find(b);
+ if (it == data.end())
+ continue;
+ const auto& src_arrivals = b.wire->get_intvec_attribute(ID::sta_arrival);
+ log_assert(GetSize(src_arrivals) == GetSize(b.wire));
+ auto src_arrival = src_arrivals[b.offset];
+ for (const auto &d : it->second.fanouts) {
+ const auto &dst_bit = std::get<0>(d);
+ auto dst_arrivals = dst_bit.wire->get_intvec_attribute(ID::sta_arrival);
+ if (dst_arrivals.empty())
+ dst_arrivals = std::vector<int>(GetSize(dst_bit.wire), -1);
+ else
+ log_assert(GetSize(dst_arrivals) == GetSize(dst_bit.wire));
+ auto &dst_arrival = dst_arrivals[dst_bit.offset];
+ auto new_arrival = src_arrival + std::get<1>(d);
+ if (dst_arrival < new_arrival) {
+ auto dst_wire = dst_bit.wire;
+ dst_arrival = std::max(dst_arrival, new_arrival);
+ dst_wire->set_intvec_attribute(ID::sta_arrival, dst_arrivals);
+ queue.emplace_back(dst_bit);
+
+ data[dst_bit].backtrack = b;
+ data[dst_bit].src_port = std::get<2>(d);
+
+ auto it = endpoints.find(dst_bit);
+ if (it != endpoints.end())
+ new_arrival += it->second.required;
+ if (new_arrival > maxarrival && driven.count(b)) {
+ maxarrival = new_arrival;
+ maxbit = dst_bit;
+ }
+ }
+ }
+ }
+
+ auto b = maxbit;
+ if (b == SigBit()) {
+ log("No timing paths found.\n");
+ return;
+ }
+
+ log("Latest arrival time in '%s' is %d:\n", log_id(module), maxarrival);
+ auto it = endpoints.find(maxbit);
+ if (it != endpoints.end() && it->second.sink)
+ log(" %6d %s (%s.%s)\n", maxarrival, log_id(it->second.sink), log_id(it->second.sink->type), log_id(it->second.port));
+ else {
+ log(" %6d (%s)\n", maxarrival, b.wire->port_output ? "<primary output>" : "<unknown>");
+ if (!b.wire->port_output)
+ log_warning("Critical-path does not terminate in a recognised endpoint.\n");
+ }
+ auto jt = data.find(b);
+ while (jt != data.end()) {
+ int arrival = b.wire->get_intvec_attribute(ID::sta_arrival)[b.offset];
+ if (jt->second.driver) {
+ log(" %s\n", log_signal(b));
+ log(" %6d %s (%s.%s->%s)\n", arrival, log_id(jt->second.driver), log_id(jt->second.driver->type), log_id(jt->second.src_port), log_id(jt->second.dst_port));
+ }
+ else if (b.wire->port_input)
+ log(" %6d %s (%s)\n", arrival, log_signal(b), "<primary input>");
+ else
+ log_abort();
+ b = jt->second.backtrack;
+ jt = data.find(b);
+ }
+
+ std::map<int, unsigned> arrival_histogram;
+ for (const auto &i : endpoints) {
+ const auto &b = i.first;
+ if (!driven.count(b))
+ continue;
+
+ if (!b.wire->attributes.count(ID::sta_arrival)) {
+ log_warning("Endpoint %s.%s has no (* sta_arrival *) value.\n", log_id(module), log_signal(b));
+ continue;
+ }
+
+ auto arrival = b.wire->get_intvec_attribute(ID::sta_arrival)[b.offset];
+ if (arrival < 0) {
+ log_warning("Endpoint %s.%s has no (* sta_arrival *) value.\n", log_id(module), log_signal(b));
+ continue;
+ }
+ arrival += i.second.required;
+ arrival_histogram[arrival]++;
+ }
+ // Adapted from https://github.com/YosysHQ/nextpnr/blob/affb12cc27ebf409eade062c4c59bb98569d8147/common/timing.cc#L946-L969
+ if (arrival_histogram.size() > 0) {
+ unsigned num_bins = 20;
+ unsigned bar_width = 60;
+ auto min_arrival = arrival_histogram.begin()->first;
+ auto max_arrival = arrival_histogram.rbegin()->first;
+ auto bin_size = std::max<unsigned>(1, ceil((max_arrival - min_arrival + 1) / float(num_bins)));
+ std::vector<unsigned> bins(num_bins);
+ unsigned max_freq = 0;
+ for (const auto &i : arrival_histogram) {
+ auto &bin = bins[(i.first - min_arrival) / bin_size];
+ bin += i.second;
+ max_freq = std::max(max_freq, bin);
+ }
+ bar_width = std::min(bar_width, max_freq);
+
+ log("\n");
+ log("Arrival histogram:\n");
+ log(" legend: * represents %d endpoint(s)\n", max_freq / bar_width);
+ log(" + represents [1,%d) endpoint(s)\n", max_freq / bar_width);
+ for (int i = num_bins-1; i >= 0; --i)
+ log("(%6d, %6d] |%s%c\n", min_arrival + bin_size * (i + 1), min_arrival + bin_size * i,
+ std::string(bins[i] * bar_width / max_freq, '*').c_str(),
+ (bins[i] * bar_width) % max_freq > 0 ? '+' : ' ');
+ }
+ }
+};
+
+struct StaPass : public Pass {
+ StaPass() : Pass("sta", "perform static timing analysis") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" sta [options] [selection]\n");
+ log("\n");
+ log("This command performs static timing analysis on the design. (Only considers\n");
+ log("paths within a single module, so the design must be flattened.)\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing STA pass (static timing analysis).\n");
+
+ /*
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-TODO") {
+ continue;
+ }
+ break;
+ }
+ */
+
+ extra_args(args, 1, design);
+
+ for (Module *module : design->selected_modules())
+ {
+ if (module->has_processes_warn())
+ continue;
+
+ StaWorker worker(module);
+ worker.run();
+ }
+ }
+} StaPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc
index 0d84c73db..fffdda48e 100644
--- a/passes/cmds/stat.cc
+++ b/passes/cmds/stat.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -117,10 +117,14 @@ struct statdata_t
}
else if (cell_type.in(ID($mux), ID($pmux)))
cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y)));
+ else if (cell_type == ID($bmux))
+ cell_type = stringf("%s_%d_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y)), GetSize(cell->getPort(ID::S)));
+ else if (cell_type == ID($demux))
+ cell_type = stringf("%s_%d_%d", cell_type.c_str(), GetSize(cell->getPort(ID::A)), GetSize(cell->getPort(ID::S)));
else if (cell_type.in(
ID($sr), ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre),
ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce),
- ID($dlatch), ID($adlatch), ID($dlatchsr)))
+ ID($aldff), ID($aldffe), ID($dlatch), ID($adlatch), ID($dlatchsr)))
cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Q)));
}
diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc
index 60689fc82..7a1f4a36b 100644
--- a/passes/cmds/tee.cc
+++ b/passes/cmds/tee.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/cmds/torder.cc b/passes/cmds/torder.cc
index 30e76081e..1620c0bca 100644
--- a/passes/cmds/torder.cc
+++ b/passes/cmds/torder.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -83,7 +83,7 @@ struct TorderPass : public Pass {
if (!noautostop && yosys_celltypes.cell_known(cell->type)) {
if (conn.first.in(ID::Q, ID::CTRL_OUT, ID::RD_DATA))
continue;
- if (cell->type == ID($memrd) && conn.first == ID::DATA)
+ if (cell->type.in(ID($memrd), ID($memrd_v2)) && conn.first == ID::DATA)
continue;
}
diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc
index 10742c370..400542776 100644
--- a/passes/cmds/trace.cc
+++ b/passes/cmds/trace.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc
index 3d898a5ef..ea9b3f556 100644
--- a/passes/cmds/write_file.cc
+++ b/passes/cmds/write_file.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/equiv/equiv_add.cc b/passes/equiv/equiv_add.cc
index 2abbb59bb..1bcd4a887 100644
--- a/passes/equiv/equiv_add.cc
+++ b/passes/equiv/equiv_add.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/equiv/equiv_induct.cc b/passes/equiv/equiv_induct.cc
index 37aec50cd..8d882ae83 100644
--- a/passes/equiv/equiv_induct.cc
+++ b/passes/equiv/equiv_induct.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -55,7 +55,10 @@ struct EquivInductWorker
for (auto cell : cells) {
if (!satgen.importCell(cell, step) && !cell_warn_cache.count(cell)) {
- log_warning("No SAT model available for cell %s (%s).\n", log_id(cell), log_id(cell->type));
+ if (RTLIL::builtin_ff_cell_types().count(cell->type))
+ log_warning("No SAT model available for async FF cell %s (%s). Consider running `async2sync` or `clk2fflogic` first.\n", log_id(cell), log_id(cell->type));
+ else
+ log_warning("No SAT model available for cell %s (%s).\n", log_id(cell), log_id(cell->type));
cell_warn_cache.insert(cell);
}
if (cell->type == ID($equiv)) {
diff --git a/passes/equiv/equiv_make.cc b/passes/equiv/equiv_make.cc
index 6923ae3d0..7ef2827bf 100644
--- a/passes/equiv/equiv_make.cc
+++ b/passes/equiv/equiv_make.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/equiv/equiv_mark.cc b/passes/equiv/equiv_mark.cc
index a722b5ed6..97a2a38dd 100644
--- a/passes/equiv/equiv_mark.cc
+++ b/passes/equiv/equiv_mark.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/equiv/equiv_miter.cc b/passes/equiv/equiv_miter.cc
index e028f806a..6acfe85a9 100644
--- a/passes/equiv/equiv_miter.cc
+++ b/passes/equiv/equiv_miter.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/equiv/equiv_purge.cc b/passes/equiv/equiv_purge.cc
index a43ecec5a..5b0696d9b 100644
--- a/passes/equiv/equiv_purge.cc
+++ b/passes/equiv/equiv_purge.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/equiv/equiv_remove.cc b/passes/equiv/equiv_remove.cc
index 89442308b..5d1823e12 100644
--- a/passes/equiv/equiv_remove.cc
+++ b/passes/equiv/equiv_remove.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/equiv/equiv_simple.cc b/passes/equiv/equiv_simple.cc
index 408c5a793..7621341a7 100644
--- a/passes/equiv/equiv_simple.cc
+++ b/passes/equiv/equiv_simple.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -184,8 +184,12 @@ struct EquivSimpleWorker
for (auto cell : problem_cells) {
auto key = pair<Cell*, int>(cell, step+1);
- if (!imported_cells_cache.count(key) && !satgen.importCell(cell, step+1))
- log_cmd_error("No SAT model available for cell %s (%s).\n", log_id(cell), log_id(cell->type));
+ if (!imported_cells_cache.count(key) && !satgen.importCell(cell, step+1)) {
+ if (RTLIL::builtin_ff_cell_types().count(cell->type))
+ log_cmd_error("No SAT model available for async FF cell %s (%s). Consider running `async2sync` or `clk2fflogic` first.\n", log_id(cell), log_id(cell->type));
+ else
+ log_cmd_error("No SAT model available for cell %s (%s).\n", log_id(cell), log_id(cell->type));
+ }
imported_cells_cache.insert(key);
}
diff --git a/passes/equiv/equiv_status.cc b/passes/equiv/equiv_status.cc
index 2db44ea90..b221be27c 100644
--- a/passes/equiv/equiv_status.cc
+++ b/passes/equiv/equiv_status.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/equiv/equiv_struct.cc b/passes/equiv/equiv_struct.cc
index 9784225db..39604994a 100644
--- a/passes/equiv/equiv_struct.cc
+++ b/passes/equiv/equiv_struct.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/fsm/fsm.cc b/passes/fsm/fsm.cc
index 21d352407..0c5e624dc 100644
--- a/passes/fsm/fsm.cc
+++ b/passes/fsm/fsm.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/fsm/fsm_detect.cc b/passes/fsm/fsm_detect.cc
index 97c575ba7..a2d38a0bd 100644
--- a/passes/fsm/fsm_detect.cc
+++ b/passes/fsm/fsm_detect.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/fsm/fsm_expand.cc b/passes/fsm/fsm_expand.cc
index d6b492af5..239f17f36 100644
--- a/passes/fsm/fsm_expand.cc
+++ b/passes/fsm/fsm_expand.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/fsm/fsm_export.cc b/passes/fsm/fsm_export.cc
index be6702d7e..65dda1267 100644
--- a/passes/fsm/fsm_export.cc
+++ b/passes/fsm/fsm_export.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2012 Martin Schmölzer <martin@schmoelzer.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/fsm/fsm_extract.cc b/passes/fsm/fsm_extract.cc
index 082973153..62a9d309e 100644
--- a/passes/fsm/fsm_extract.cc
+++ b/passes/fsm/fsm_extract.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/fsm/fsm_info.cc b/passes/fsm/fsm_info.cc
index da0982bb9..ff3714021 100644
--- a/passes/fsm/fsm_info.cc
+++ b/passes/fsm/fsm_info.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/fsm/fsm_map.cc b/passes/fsm/fsm_map.cc
index a30d407f0..df31dbb7a 100644
--- a/passes/fsm/fsm_map.cc
+++ b/passes/fsm/fsm_map.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/fsm/fsm_opt.cc b/passes/fsm/fsm_opt.cc
index 5fc1fb3bb..f2eb06760 100644
--- a/passes/fsm/fsm_opt.cc
+++ b/passes/fsm/fsm_opt.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/fsm/fsm_recode.cc b/passes/fsm/fsm_recode.cc
index d4a704270..3dc29b5a0 100644
--- a/passes/fsm/fsm_recode.cc
+++ b/passes/fsm/fsm_recode.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/fsm/fsmdata.h b/passes/fsm/fsmdata.h
index 47398b558..4ba3b4e4f 100644
--- a/passes/fsm/fsmdata.h
+++ b/passes/fsm/fsmdata.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc
index 3372687e1..440881f19 100644
--- a/passes/hierarchy/hierarchy.cc
+++ b/passes/hierarchy/hierarchy.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2018 Ruben Undheim <ruben.undheim@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -156,6 +156,289 @@ std::string basic_cell_type(const std::string celltype, int pos[3] = nullptr) {
return basicType;
}
+// A helper struct for expanding a module's interface connections in expand_module
+struct IFExpander
+{
+ IFExpander (RTLIL::Design &design, RTLIL::Module &m)
+ : module(m), has_interfaces_not_found(false)
+ {
+ // Keep track of all derived interfaces available in the current
+ // module in 'interfaces_in_module':
+ for (auto cell : module.cells()) {
+ if(!cell->get_bool_attribute(ID::is_interface))
+ continue;
+
+ interfaces_in_module[cell->name] = design.module(cell->type);
+ }
+ }
+
+ RTLIL::Module &module;
+ dict<RTLIL::IdString, RTLIL::Module*> interfaces_in_module;
+
+ bool has_interfaces_not_found;
+ std::vector<RTLIL::IdString> connections_to_remove;
+ std::vector<RTLIL::IdString> connections_to_add_name;
+ std::vector<RTLIL::SigSpec> connections_to_add_signal;
+ dict<RTLIL::IdString, RTLIL::Module*> interfaces_to_add_to_submodule;
+ dict<RTLIL::IdString, RTLIL::IdString> modports_used_in_submodule;
+
+ // Reset the per-cell state
+ void start_cell()
+ {
+ has_interfaces_not_found = false;
+ connections_to_remove.clear();
+ connections_to_add_name.clear();
+ connections_to_add_signal.clear();
+ interfaces_to_add_to_submodule.clear();
+ modports_used_in_submodule.clear();
+ }
+
+ // Set has_interfaces_not_found if there are pending interfaces that
+ // haven't been found yet (and might be found in the future). Print a
+ // warning if we've already gone over all the cells in the module.
+ void on_missing_interface(RTLIL::IdString interface_name)
+ {
+ // If there are cells that haven't yet been processed, maybe
+ // we'll find this interface in the future.
+ if (module.get_bool_attribute(ID::cells_not_processed)) {
+ has_interfaces_not_found = true;
+ return;
+ }
+
+ // Otherwise, we have already gone over all cells in this
+ // module and the interface has still not been found. Warn
+ // about it and don't set has_interfaces_not_found (to avoid a
+ // loop).
+ log_warning("Could not find interface instance for `%s' in `%s'\n",
+ log_id(interface_name), log_id(&module));
+ }
+
+ // Handle an interface connection from the module
+ void on_interface(RTLIL::Module &submodule,
+ RTLIL::IdString conn_name,
+ const RTLIL::SigSpec &conn_signals)
+ {
+ // Check if the connected wire is a potential interface in the parent module
+ std::string interface_name_str = conn_signals.bits()[0].wire->name.str();
+ // Strip the prefix '$dummywireforinterface' from the dummy wire to get the name
+ interface_name_str.replace(0,23,"");
+ interface_name_str = "\\" + interface_name_str;
+ RTLIL::IdString interface_name = interface_name_str;
+
+ // If 'interfaces' in the cell have not be been handled yet, we aren't
+ // ready to derive the sub-module either
+ if (!module.get_bool_attribute(ID::interfaces_replaced_in_module)) {
+ on_missing_interface(interface_name);
+ return;
+ }
+
+ // Check if the interface instance is present in module. Interface
+ // instances may either have the plain name or the name appended with
+ // '_inst_from_top_dummy'. Check for both of them here
+ int nexactmatch = interfaces_in_module.count(interface_name) > 0;
+ std::string interface_name_str2 = interface_name_str + "_inst_from_top_dummy";
+ RTLIL::IdString interface_name2 = interface_name_str2;
+ int nmatch2 = interfaces_in_module.count(interface_name2) > 0;
+
+ // If we can't find either name, this is a missing interface.
+ if (! (nexactmatch || nmatch2)) {
+ on_missing_interface(interface_name);
+ return;
+ }
+
+ if (nexactmatch != 0) // Choose the one with the plain name if it exists
+ interface_name2 = interface_name;
+
+ RTLIL::Module *mod_replace_ports = interfaces_in_module.at(interface_name2);
+
+ // Go over all wires in interface, and add replacements to lists.
+ for (auto mod_wire : mod_replace_ports->wires()) {
+ std::string signal_name1 = conn_name.str() + "." + log_id(mod_wire->name);
+ std::string signal_name2 = interface_name.str() + "." + log_id(mod_wire);
+ connections_to_add_name.push_back(RTLIL::IdString(signal_name1));
+ if(module.wire(signal_name2) == nullptr) {
+ log_error("Could not find signal '%s' in '%s'\n",
+ signal_name2.c_str(), log_id(module.name));
+ }
+ else {
+ RTLIL::Wire *wire_in_parent = module.wire(signal_name2);
+ connections_to_add_signal.push_back(wire_in_parent);
+ }
+ }
+ connections_to_remove.push_back(conn_name);
+ interfaces_to_add_to_submodule[conn_name] = interfaces_in_module.at(interface_name2);
+
+ // Find if the sub-module has set a modport for the current interface
+ // connection. Add any modports to a dict which will be passed to
+ // AstModule::derive
+ string modport_name = submodule.wire(conn_name)->get_string_attribute(ID::interface_modport);
+ if (!modport_name.empty()) {
+ modports_used_in_submodule[conn_name] = "\\" + modport_name;
+ }
+ }
+
+ // Handle a single connection from the module, making a note to expand
+ // it if it's an interface connection.
+ void on_connection(RTLIL::Module &submodule,
+ RTLIL::IdString conn_name,
+ const RTLIL::SigSpec &conn_signals)
+ {
+ // Check if the connection is present as an interface in the sub-module's port list
+ const RTLIL::Wire *wire = submodule.wire(conn_name);
+ if (!wire || !wire->get_bool_attribute(ID::is_interface))
+ return;
+
+ // If the connection looks like an interface, handle it.
+ const auto &bits = conn_signals.bits();
+ if (bits.size() == 1 && bits[0].wire->get_bool_attribute(ID::is_interface))
+ on_interface(submodule, conn_name, conn_signals);
+ }
+
+ // Iterate over the connections in a cell, tracking any interface
+ // connections
+ void visit_connections(const RTLIL::Cell &cell,
+ RTLIL::Module &submodule)
+ {
+ for (const auto &conn : cell.connections()) {
+ on_connection(submodule, conn.first, conn.second);
+ }
+ }
+
+ // Add/remove connections to the cell as necessary, replacing any SV
+ // interface port connection with the individual signal connections.
+ void rewrite_interface_connections(RTLIL::Cell &cell) const
+ {
+ for(unsigned int i=0;i<connections_to_add_name.size();i++) {
+ cell.connections_[connections_to_add_name[i]] = connections_to_add_signal[i];
+ }
+ // Remove the connection for the interface itself:
+ for(unsigned int i=0;i<connections_to_remove.size();i++) {
+ cell.connections_.erase(connections_to_remove[i]);
+ }
+ }
+};
+
+// Get a module needed by a cell, either by deriving an abstract module or by
+// loading one from a directory in libdirs.
+//
+// If the module can't be found and check is true then exit with an error
+// message. Otherwise, return a pointer to the module if we derived or loaded
+// something. or null otherwise (the module should be blackbox or we couldn't
+// find it and check is not set).
+RTLIL::Module *get_module(RTLIL::Design &design,
+ RTLIL::Cell &cell,
+ RTLIL::Module &parent,
+ bool check,
+ const std::vector<std::string> &libdirs)
+{
+ std::string cell_type = cell.type.str();
+ RTLIL::Module *abs_mod = design.module("$abstract" + cell_type);
+ if (abs_mod) {
+ cell.type = abs_mod->derive(&design, cell.parameters);
+ cell.parameters.clear();
+ RTLIL::Module *mod = design.module(cell.type);
+ log_assert(mod);
+ return mod;
+ }
+
+ // If the cell type starts with '$' and isn't '$abstract', we should
+ // treat it as a black box and skip.
+ if (cell_type[0] == '$')
+ return nullptr;
+
+ for (auto &dir : libdirs) {
+ static const vector<pair<string, string>> extensions_list =
+ {
+ {".v", "verilog"},
+ {".sv", "verilog -sv"},
+ {".il", "rtlil"}
+ };
+
+ for (auto &ext : extensions_list) {
+ std::string filename = dir + "/" + RTLIL::unescape_id(cell.type) + ext.first;
+ if (!check_file_exists(filename))
+ continue;
+
+ Frontend::frontend_call(&design, NULL, filename, ext.second);
+ RTLIL::Module *mod = design.module(cell.type);
+ if (!mod)
+ log_error("File `%s' from libdir does not declare module `%s'.\n",
+ filename.c_str(), cell_type.c_str());
+ return mod;
+ }
+ }
+
+ // We couldn't find the module anywhere. Complain if check is set.
+ if (check)
+ log_error("Module `%s' referenced in module `%s' in cell `%s' is not part of the design.\n",
+ cell_type.c_str(), parent.name.c_str(), cell.name.c_str());
+
+ return nullptr;
+}
+
+// Try to read an IdString as a numbered connection name ("$123" or similar),
+// writing the result to dst. If the string isn't of the right format, ignore
+// dst and return false.
+bool read_id_num(RTLIL::IdString str, int *dst)
+{
+ log_assert(dst);
+
+ const char *c_str = str.c_str();
+ if (c_str[0] != '$' || !('0' <= c_str[1] && c_str[1] <= '9'))
+ return false;
+
+ *dst = atoi(c_str + 1);
+ return true;
+}
+
+// Check that the connections on the cell match those that are defined
+// on the type: each named connection should match the name of a port
+// and each positional connection should have an index smaller than
+// the number of ports.
+//
+// Also do the same checks on the specified parameters.
+void check_cell_connections(const RTLIL::Module &module, RTLIL::Cell &cell, RTLIL::Module &mod)
+{
+ int id;
+ for (auto &conn : cell.connections()) {
+ if (read_id_num(conn.first, &id)) {
+ if (id <= 0 || id > GetSize(mod.ports))
+ log_error("Module `%s' referenced in module `%s' in cell `%s' "
+ "has only %d ports, requested port %d.\n",
+ log_id(cell.type), log_id(&module), log_id(&cell),
+ GetSize(mod.ports), id);
+ continue;
+ }
+
+ const RTLIL::Wire* wire = mod.wire(conn.first);
+ if (!wire || wire->port_id == 0) {
+ log_error("Module `%s' referenced in module `%s' in cell `%s' "
+ "does not have a port named '%s'.\n",
+ log_id(cell.type), log_id(&module), log_id(&cell),
+ log_id(conn.first));
+ }
+ }
+ for (auto &param : cell.parameters) {
+ if (read_id_num(param.first, &id)) {
+ if (id <= 0 || id > GetSize(mod.avail_parameters))
+ log_error("Module `%s' referenced in module `%s' in cell `%s' "
+ "has only %d parameters, requested parameter %d.\n",
+ log_id(cell.type), log_id(&module), log_id(&cell),
+ GetSize(mod.avail_parameters), id);
+ continue;
+ }
+
+ if (mod.avail_parameters.count(param.first) == 0 &&
+ param.first[0] != '$' &&
+ strchr(param.first.c_str(), '.') == NULL) {
+ log_error("Module `%s' referenced in module `%s' in cell `%s' "
+ "does not have a parameter named '%s'.\n",
+ log_id(cell.type), log_id(&module), log_id(&cell),
+ log_id(param.first));
+ }
+ }
+}
+
bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, std::vector<std::string> &libdirs)
{
bool did_something = false;
@@ -173,23 +456,11 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
}
}
- // Always keep track of all derived interfaces available in the current module in 'interfaces_in_module':
- dict<RTLIL::IdString, RTLIL::Module*> interfaces_in_module;
- for (auto cell : module->cells())
- {
- if(cell->get_bool_attribute(ID::is_interface)) {
- RTLIL::Module *intf_module = design->module(cell->type);
- interfaces_in_module[cell->name] = intf_module;
- }
- }
+ IFExpander if_expander(*design, *module);
for (auto cell : module->cells())
{
- bool has_interfaces_not_found = false;
-
- std::vector<RTLIL::IdString> connections_to_remove;
- std::vector<RTLIL::IdString> connections_to_add_name;
- std::vector<RTLIL::SigSpec> connections_to_add_signal;
+ if_expander.start_cell();
if (cell->type.begins_with("$array:")) {
int pos[3];
@@ -202,147 +473,32 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
array_cells[cell] = std::pair<int, int>(idx, num);
cell->type = cell->type.substr(pos_type + 1);
}
- dict<RTLIL::IdString, RTLIL::Module*> interfaces_to_add_to_submodule;
- dict<RTLIL::IdString, RTLIL::IdString> modports_used_in_submodule;
- if (design->module(cell->type) == nullptr)
+ RTLIL::Module *mod = design->module(cell->type);
+ if (!mod)
{
- if (design->module("$abstract" + cell->type.str()) != nullptr)
- {
- cell->type = design->module("$abstract" + cell->type.str())->derive(design, cell->parameters);
- cell->parameters.clear();
- did_something = true;
- continue;
- }
+ mod = get_module(*design, *cell, *module, flag_check || flag_simcheck, libdirs);
- if (cell->type[0] == '$')
- continue;
-
- for (auto &dir : libdirs)
- {
- static const vector<pair<string, string>> extensions_list =
- {
- {".v", "verilog"},
- {".sv", "verilog -sv"},
- {".il", "rtlil"}
- };
-
- for (auto &ext : extensions_list)
- {
- filename = dir + "/" + RTLIL::unescape_id(cell->type) + ext.first;
- if (check_file_exists(filename)) {
- Frontend::frontend_call(design, NULL, filename, ext.second);
- goto loaded_module;
- }
- }
- }
+ // If we still don't have a module, treat the cell as a black box and skip
+ // it. Otherwise, we either loaded or derived something so should set the
+ // did_something flag before returning (to ensure we come back and expand
+ // the thing we just loaded).
+ if (mod)
+ did_something = true;
- if ((flag_check || flag_simcheck) && cell->type[0] != '$')
- log_error("Module `%s' referenced in module `%s' in cell `%s' is not part of the design.\n",
- cell->type.c_str(), module->name.c_str(), cell->name.c_str());
continue;
+ }
- loaded_module:
- if (design->module(cell->type) == nullptr)
- log_error("File `%s' from libdir does not declare module `%s'.\n", filename.c_str(), cell->type.c_str());
- did_something = true;
- } else {
-
- RTLIL::Module *mod = design->module(cell->type);
+ log_assert(mod);
- // Go over all connections and see if any of them are SV interfaces. If they are, then add the replacements to
- // some lists, so that the ports for sub-modules can be replaced further down:
- for (auto &conn : cell->connections()) {
- if(mod->wire(conn.first) != nullptr && mod->wire(conn.first)->get_bool_attribute(ID::is_interface)) { // Check if the connection is present as an interface in the sub-module's port list
- if(conn.second.bits().size() == 1 && conn.second.bits()[0].wire->get_bool_attribute(ID::is_interface)) { // Check if the connected wire is a potential interface in the parent module
- std::string interface_name_str = conn.second.bits()[0].wire->name.str();
- interface_name_str.replace(0,23,""); // Strip the prefix '$dummywireforinterface' from the dummy wire to get the name
- interface_name_str = "\\" + interface_name_str;
- RTLIL::IdString interface_name = interface_name_str;
- bool not_found_interface = false;
- if(module->get_bool_attribute(ID::interfaces_replaced_in_module)) { // If 'interfaces' in the cell have not be been handled yet, there is no need to derive the sub-module either
- // Check if the interface instance is present in module:
- // Interface instances may either have the plain name or the name appended with '_inst_from_top_dummy'.
- // Check for both of them here
- int nexactmatch = interfaces_in_module.count(interface_name) > 0;
- std::string interface_name_str2 = interface_name_str + "_inst_from_top_dummy";
- RTLIL::IdString interface_name2 = interface_name_str2;
- int nmatch2 = interfaces_in_module.count(interface_name2) > 0;
- if (nexactmatch > 0 || nmatch2 > 0) {
- if (nexactmatch != 0) // Choose the one with the plain name if it exists
- interface_name2 = interface_name;
- RTLIL::Module *mod_replace_ports = interfaces_in_module.at(interface_name2);
- for (auto mod_wire : mod_replace_ports->wires()) { // Go over all wires in interface, and add replacements to lists.
- std::string signal_name1 = conn.first.str() + "." + log_id(mod_wire->name);
- std::string signal_name2 = interface_name.str() + "." + log_id(mod_wire);
- connections_to_add_name.push_back(RTLIL::IdString(signal_name1));
- if(module->wire(signal_name2) == nullptr) {
- log_error("Could not find signal '%s' in '%s'\n", signal_name2.c_str(), log_id(module->name));
- }
- else {
- RTLIL::Wire *wire_in_parent = module->wire(signal_name2);
- connections_to_add_signal.push_back(wire_in_parent);
- }
- }
- connections_to_remove.push_back(conn.first);
- interfaces_to_add_to_submodule[conn.first] = interfaces_in_module.at(interface_name2);
-
- // Find if the sub-module has set a modport for the current
- // interface connection. Add any modports to a dict which will
- // be passed to AstModule::derive
- string modport_name = mod->wire(conn.first)->get_string_attribute(ID::interface_modport);
- if (!modport_name.empty()) {
- modports_used_in_submodule[conn.first] = "\\" + modport_name;
- }
- }
- else not_found_interface = true;
- }
- else not_found_interface = true;
- // If the interface instance has not already been derived in the module, we cannot complete at this stage. Set "has_interfaces_not_found"
- // which will delay the expansion of this cell:
- if (not_found_interface) {
- // If we have already gone over all cells in this module, and the interface has still not been found - flag it as an error:
- if(!(module->get_bool_attribute(ID::cells_not_processed))) {
- log_warning("Could not find interface instance for `%s' in `%s'\n", log_id(interface_name), log_id(module));
- }
- else {
- // Only set has_interfaces_not_found if it would be possible to find them, since otherwiser we will end up in an infinite loop:
- has_interfaces_not_found = true;
- }
- }
- }
- }
- }
- //
+ // Go over all connections and check if any of them are SV
+ // interfaces.
+ if_expander.visit_connections(*cell, *mod);
if (flag_check || flag_simcheck)
- {
- for (auto &conn : cell->connections()) {
- if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') {
- int id = atoi(conn.first.c_str()+1);
- if (id <= 0 || id > GetSize(mod->ports))
- log_error("Module `%s' referenced in module `%s' in cell `%s' has only %d ports, requested port %d.\n",
- log_id(cell->type), log_id(module), log_id(cell), GetSize(mod->ports), id);
- } else if (mod->wire(conn.first) == nullptr || mod->wire(conn.first)->port_id == 0)
- log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a port named '%s'.\n",
- log_id(cell->type), log_id(module), log_id(cell), log_id(conn.first));
- }
- for (auto &param : cell->parameters) {
- if (param.first[0] == '$' && '0' <= param.first[1] && param.first[1] <= '9') {
- int id = atoi(param.first.c_str()+1);
- if (id <= 0 || id > GetSize(mod->avail_parameters))
- log_error("Module `%s' referenced in module `%s' in cell `%s' has only %d parameters, requested parameter %d.\n",
- log_id(cell->type), log_id(module), log_id(cell), GetSize(mod->avail_parameters), id);
- } else if (mod->avail_parameters.count(param.first) == 0 && param.first[0] != '$' && strchr(param.first.c_str(), '.') == NULL)
- log_error("Module `%s' referenced in module `%s' in cell `%s' does not have a parameter named '%s'.\n",
- log_id(cell->type), log_id(module), log_id(cell), log_id(param.first));
- }
-
- }
- }
- RTLIL::Module *mod = design->module(cell->type);
+ check_cell_connections(*module, *cell, *mod);
- if (design->module(cell->type)->get_blackbox_attribute()) {
+ if (mod->get_blackbox_attribute()) {
if (flag_simcheck)
log_error("Module `%s' referenced in module `%s' in cell `%s' is a blackbox/whitebox module.\n",
cell->type.c_str(), module->name.c_str(), cell->name.c_str());
@@ -350,23 +506,18 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
}
// If interface instances not yet found, skip cell for now, and say we did something, so that we will return back here:
- if(has_interfaces_not_found) {
+ if(if_expander.has_interfaces_not_found) {
did_something = true; // waiting for interfaces to be handled
continue;
}
- // Do the actual replacements of the SV interface port connection with the individual signal connections:
- for(unsigned int i=0;i<connections_to_add_name.size();i++) {
- cell->connections_[connections_to_add_name[i]] = connections_to_add_signal[i];
- }
- // Remove the connection for the interface itself:
- for(unsigned int i=0;i<connections_to_remove.size();i++) {
- cell->connections_.erase(connections_to_remove[i]);
- }
+ if_expander.rewrite_interface_connections(*cell);
// If there are no overridden parameters AND not interfaces, then we can use the existing module instance as the type
// for the cell:
- if (cell->parameters.size() == 0 && (interfaces_to_add_to_submodule.size() == 0 || !(cell->get_bool_attribute(ID::module_not_derived)))) {
+ if (cell->parameters.size() == 0 &&
+ (if_expander.interfaces_to_add_to_submodule.size() == 0 ||
+ !(cell->get_bool_attribute(ID::module_not_derived)))) {
// If the cell being processed is an the interface instance itself, go down to "handle_interface_instance:",
// so that the signals of the interface are added to the parent module.
if (mod->get_bool_attribute(ID::is_interface)) {
@@ -375,7 +526,10 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
continue;
}
- cell->type = mod->derive(design, cell->parameters, interfaces_to_add_to_submodule, modports_used_in_submodule);
+ cell->type = mod->derive(design,
+ cell->parameters,
+ if_expander.interfaces_to_add_to_submodule,
+ if_expander.modports_used_in_submodule);
cell->parameters.clear();
did_something = true;
@@ -386,7 +540,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
if (mod->get_bool_attribute(ID::is_interface) && cell->get_bool_attribute(ID::module_not_derived)) {
cell->set_bool_attribute(ID::is_interface);
RTLIL::Module *derived_module = design->module(cell->type);
- interfaces_in_module[cell->name] = derived_module;
+ if_expander.interfaces_in_module[cell->name] = derived_module;
did_something = true;
}
// We clear 'module_not_derived' such that we will not rederive the cell again (needed when there are interfaces connected to the cell)
@@ -399,11 +553,15 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
// If any interface instances or interface ports were found in the module, we need to rederive it completely:
- if ((interfaces_in_module.size() > 0 || has_interface_ports) && !module->get_bool_attribute(ID::interfaces_replaced_in_module)) {
- module->reprocess_module(design, interfaces_in_module);
+ if ((if_expander.interfaces_in_module.size() > 0 || has_interface_ports) && !module->get_bool_attribute(ID::interfaces_replaced_in_module)) {
+ module->expand_interfaces(design, if_expander.interfaces_in_module);
return did_something;
}
+ // Now that modules have been derived, we may want to reprocess this
+ // module given the additional available context.
+ if (module->reprocess_if_necessary(design))
+ return true;
for (auto &it : array_cells)
{
@@ -952,8 +1110,8 @@ struct HierarchyPass : public Pass {
pool<std::pair<IdString, IdString>> params_rename;
for (const auto &p : cell->parameters) {
- if (p.first[0] == '$' && '0' <= p.first[1] && p.first[1] <= '9') {
- int id = atoi(p.first.c_str()+1);
+ int id;
+ if (read_id_num(p.first, &id)) {
if (id <= 0 || id > GetSize(cell_mod->avail_parameters)) {
log(" Failed to map positional parameter %d of cell %s.%s (%s).\n",
id, RTLIL::id2cstr(mod->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
@@ -980,9 +1138,9 @@ struct HierarchyPass : public Pass {
log("Mapping positional arguments of cell %s.%s (%s).\n",
RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type));
dict<RTLIL::IdString, RTLIL::SigSpec> new_connections;
- for (auto &conn : cell->connections())
- if (conn.first[0] == '$' && '0' <= conn.first[1] && conn.first[1] <= '9') {
- int id = atoi(conn.first.c_str()+1);
+ for (auto &conn : cell->connections()) {
+ int id;
+ if (read_id_num(conn.first, &id)) {
std::pair<RTLIL::Module*,int> key(design->module(cell->type), id);
if (pos_map.count(key) == 0) {
log(" Failed to map positional argument %d of cell %s.%s (%s).\n",
@@ -992,6 +1150,7 @@ struct HierarchyPass : public Pass {
new_connections[pos_map.at(key)] = conn.second;
} else
new_connections[conn.first] = conn.second;
+ }
cell->connections_ = new_connections;
}
}
diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc
index b2826cbff..845dc850f 100644
--- a/passes/hierarchy/submod.cc
+++ b/passes/hierarchy/submod.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/hierarchy/uniquify.cc b/passes/hierarchy/uniquify.cc
index 3f9443a63..e9322d359 100644
--- a/passes/hierarchy/uniquify.cc
+++ b/passes/hierarchy/uniquify.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/memory/Makefile.inc b/passes/memory/Makefile.inc
index e468c3a07..5a2c4ecfc 100644
--- a/passes/memory/Makefile.inc
+++ b/passes/memory/Makefile.inc
@@ -8,4 +8,5 @@ OBJS += passes/memory/memory_bram.o
OBJS += passes/memory/memory_map.o
OBJS += passes/memory/memory_memx.o
OBJS += passes/memory/memory_nordff.o
+OBJS += passes/memory/memory_narrow.o
diff --git a/passes/memory/memory.cc b/passes/memory/memory.cc
index 282517992..bac547c1a 100644
--- a/passes/memory/memory.cc
+++ b/passes/memory/memory.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -31,16 +31,19 @@ struct MemoryPass : public Pass {
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" memory [-nomap] [-nordff] [-memx] [-bram <bram_rules>] [selection]\n");
+ log(" memory [-nomap] [-nordff] [-nowiden] [-nosat] [-memx] [-bram <bram_rules>] [selection]\n");
log("\n");
log("This pass calls all the other memory_* passes in a useful order:\n");
log("\n");
log(" opt_mem\n");
- log(" memory_dff [-nordff] (-memx implies -nordff)\n");
- log(" opt_clean\n");
- log(" memory_share\n");
+ log(" opt_mem_priority\n");
+ log(" opt_mem_feedback\n");
+ log(" memory_dff (skipped if called with -nordff or -memx)\n");
log(" opt_clean\n");
+ log(" memory_share [-nowiden] [-nosat]\n");
+ log(" opt_mem_widen\n");
log(" memory_memx (when called with -memx)\n");
+ log(" opt_clean\n");
log(" memory_collect\n");
log(" memory_bram -rules <bram_rules> (when called with -bram)\n");
log(" memory_map (skipped if called with -nomap)\n");
@@ -55,6 +58,7 @@ struct MemoryPass : public Pass {
bool flag_nordff = false;
bool flag_memx = false;
string memory_bram_opts;
+ string memory_share_opts;
log_header(design, "Executing MEMORY pass.\n");
log_push();
@@ -74,6 +78,14 @@ struct MemoryPass : public Pass {
flag_memx = true;
continue;
}
+ if (args[argidx] == "-nowiden") {
+ memory_share_opts += " -nowiden";
+ continue;
+ }
+ if (args[argidx] == "-nosat") {
+ memory_share_opts += " -nosat";
+ continue;
+ }
if (argidx+1 < args.size() && args[argidx] == "-bram") {
memory_bram_opts += " -rules " + args[++argidx];
continue;
@@ -83,9 +95,13 @@ struct MemoryPass : public Pass {
extra_args(args, argidx, design);
Pass::call(design, "opt_mem");
- Pass::call(design, flag_nordff ? "memory_dff -nordff" : "memory_dff");
+ Pass::call(design, "opt_mem_priority");
+ Pass::call(design, "opt_mem_feedback");
+ if (!flag_nordff)
+ Pass::call(design, "memory_dff");
Pass::call(design, "opt_clean");
- Pass::call(design, "memory_share");
+ Pass::call(design, "memory_share" + memory_share_opts);
+ Pass::call(design, "opt_mem_widen");
if (flag_memx)
Pass::call(design, "memory_memx");
Pass::call(design, "opt_clean");
diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc
index c6948fdba..b1f45d5fc 100644
--- a/passes/memory/memory_bram.cc
+++ b/passes/memory/memory_bram.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/mem.h"
+#include "kernel/ffinit.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -29,9 +30,6 @@ struct rules_t
int group, index, dupidx;
int wrmode, enable, transp, clocks, clkpol;
- SigBit sig_clock;
- SigSpec sig_addr, sig_data, sig_en;
- bool effective_clkpol;
bool make_transp;
bool make_outreg;
int mapped_port;
@@ -92,7 +90,6 @@ struct rules_t
pi.mapped_port = -1;
pi.make_transp = false;
pi.make_outreg = false;
- pi.effective_clkpol = false;
portinfos.push_back(pi);
}
return portinfos;
@@ -401,19 +398,13 @@ struct rules_t
}
};
-bool replace_memory(Mem &orig_mem, const rules_t &rules, const rules_t::bram_t &bram, const rules_t::match_t &match, dict<string, int> &match_properties, int mode)
+bool replace_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals, const rules_t::bram_t &bram, const rules_t::match_t &match, dict<string, int> &match_properties, int mode)
{
- // We will modify ports — make a copy of the structure.
- Mem mem(orig_mem);
Module *module = mem.module;
auto portinfos = bram.make_portinfos();
int dup_count = 1;
- pair<SigBit, bool> make_transp_clk;
- bool enable_make_transp = false;
- int make_transp_enbits = 0;
-
dict<int, pair<SigBit, bool>> clock_domains;
dict<int, bool> clock_polarities;
dict<int, bool> read_transp;
@@ -440,35 +431,12 @@ bool replace_memory(Mem &orig_mem, const rules_t &rules, const rules_t::bram_t &
log(" Mapping to bram type %s (variant %d):\n", log_id(bram.name), bram.variant);
// bram.dump_config();
- bool cell_init = !mem.inits.empty();
- vector<Const> initdata;
-
- if (cell_init) {
- Const initparam = mem.get_init_data();
- initdata.reserve(mem.size);
- for (int i=0; i < mem.size; i++)
- initdata.push_back(initparam.extract(mem.width*i, mem.width, State::Sx));
- }
-
+ std::vector<int> shuffle_map;
if (match.shuffle_enable && bram.dbits >= portinfos.at(match.shuffle_enable - 'A').enable*2 && portinfos.at(match.shuffle_enable - 'A').enable > 0 && !mem.wr_ports.empty())
{
int bucket_size = bram.dbits / portinfos.at(match.shuffle_enable - 'A').enable;
log(" Shuffle bit order to accommodate enable buckets of size %d..\n", bucket_size);
- // extract unshuffled data/enable bits
-
- std::vector<SigSpec> old_wr_en;
- std::vector<SigSpec> old_wr_data;
- std::vector<SigSpec> old_rd_data;
-
- for (auto &port : mem.wr_ports) {
- old_wr_en.push_back(port.en);
- old_wr_data.push_back(port.data);
- }
-
- for (auto &port : mem.rd_ports)
- old_rd_data.push_back(port.data);
-
// analyze enable structure
std::vector<SigSpec> en_order;
@@ -483,52 +451,13 @@ bool replace_memory(Mem &orig_mem, const rules_t &rules, const rules_t::bram_t &
bits_wr_en[sig].push_back(i);
}
- // re-create memory ports
-
- std::vector<SigSpec> new_wr_en(GetSize(old_wr_en));
- std::vector<SigSpec> new_wr_data(GetSize(old_wr_data));
- std::vector<SigSpec> new_rd_data(GetSize(old_rd_data));
- std::vector<std::vector<State>> new_initdata;
- std::vector<int> shuffle_map;
-
- if (cell_init)
- new_initdata.resize(mem.size);
-
for (auto &it : en_order)
{
- auto &bits = bits_wr_en.at(it);
- int buckets = (GetSize(bits) + bucket_size - 1) / bucket_size;
- int fillbits = buckets*bucket_size - GetSize(bits);
- SigBit fillbit;
-
- for (int i = 0; i < GetSize(bits); i++) {
- for (int j = 0; j < GetSize(mem.wr_ports); j++) {
- new_wr_en[j].append(old_wr_en[j][bits[i]]);
- new_wr_data[j].append(old_wr_data[j][bits[i]]);
- fillbit = old_wr_en[j][bits[i]];
- }
- for (int j = 0; j < GetSize(mem.rd_ports); j++)
- new_rd_data[j].append(old_rd_data[j][bits[i]]);
- if (cell_init) {
- for (int j = 0; j < mem.size; j++)
- new_initdata[j].push_back(initdata[j][bits[i]]);
- }
- shuffle_map.push_back(bits[i]);
- }
+ for (auto bit : bits_wr_en.at(it))
+ shuffle_map.push_back(bit);
- for (int i = 0; i < fillbits; i++) {
- for (int j = 0; j < GetSize(mem.wr_ports); j++) {
- new_wr_en[j].append(fillbit);
- new_wr_data[j].append(State::S0);
- }
- for (int j = 0; j < GetSize(mem.rd_ports); j++)
- new_rd_data[j].append(State::Sx);
- if (cell_init) {
- for (int j = 0; j < mem.size; j++)
- new_initdata[j].push_back(State::Sx);
- }
+ while (GetSize(shuffle_map) % bucket_size)
shuffle_map.push_back(-1);
- }
}
log(" Results of bit order shuffling:");
@@ -537,26 +466,15 @@ bool replace_memory(Mem &orig_mem, const rules_t &rules, const rules_t::bram_t &
log("\n");
// update mem_*, wr_*, and rd_* variables
-
- mem.width = GetSize(new_wr_en.front());
-
- for (int i = 0; i < GetSize(mem.wr_ports); i++) {
- auto &port = mem.wr_ports[i];
- port.en = new_wr_en[i];
- port.data = new_wr_data[i];
- }
-
- for (int i = 0; i < GetSize(mem.rd_ports); i++) {
- auto &port = mem.rd_ports[i];
- port.data = new_rd_data[i];
- }
-
- if (cell_init) {
- for (int i = 0; i < mem.size; i++)
- initdata[i] = Const(new_initdata[i]);
- }
+ } else {
+ for (int i = 0; i < mem.width; i++)
+ shuffle_map.push_back(i);
}
+ // Align width up to dbits.
+ while (GetSize(shuffle_map) % bram.dbits)
+ shuffle_map.push_back(-1);
+
// assign write ports
pair<SigBit, bool> wr_clkdom;
for (int cell_port_i = 0, bram_port_i = 0; cell_port_i < GetSize(mem.wr_ports); cell_port_i++)
@@ -574,8 +492,6 @@ bool replace_memory(Mem &orig_mem, const rules_t &rules, const rules_t::bram_t &
for (; bram_port_i < GetSize(portinfos); bram_port_i++)
{
auto &pi = portinfos[bram_port_i];
- make_transp_enbits = pi.enable;
- make_transp_clk = clkdom;
if (pi.wrmode != 1)
skip_bram_wport:
@@ -601,16 +517,25 @@ bool replace_memory(Mem &orig_mem, const rules_t &rules, const rules_t::bram_t &
}
}
- SigSpec sig_en;
- SigBit last_en_bit = State::S1;
- for (int i = 0; i < mem.width; i++) {
- if (pi.enable && i % (bram.dbits / pi.enable) == 0) {
- last_en_bit = port.en[i];
- sig_en.append(last_en_bit);
- }
- if (last_en_bit != port.en[i]) {
- log(" Bram port %c%d has incompatible enable structure.\n", pi.group + 'A', pi.index + 1);
- goto skip_bram_wport;
+ // We need to check enable compatibility of this port, as well as all
+ // ports that have priority over this one (because they will be involved
+ // in emulate_priority logic).
+
+ for (int i = 0; i < GetSize(mem.wr_ports); i++) {
+ auto &oport = mem.wr_ports[i];
+ if (i != cell_port_i && !oport.priority_mask[cell_port_i])
+ continue;
+ SigBit last_en_bit = State::S1;
+ for (int j = 0; j < GetSize(shuffle_map); j++) {
+ if (shuffle_map[j] == -1)
+ continue;
+ SigBit en_bit = oport.en[shuffle_map[j]];
+ if (pi.enable && j % (bram.dbits / pi.enable) == 0)
+ last_en_bit = en_bit;
+ if (last_en_bit != en_bit) {
+ log(" Bram port %c%d has incompatible enable structure.\n", pi.group + 'A', pi.index + 1);
+ goto skip_bram_wport;
+ }
}
}
@@ -620,14 +545,8 @@ bool replace_memory(Mem &orig_mem, const rules_t &rules, const rules_t::bram_t &
if (port.clk_enable) {
clock_domains[pi.clocks] = clkdom;
clock_polarities[pi.clkpol] = clkdom.second;
- pi.sig_clock = clkdom.first;
- pi.effective_clkpol = clkdom.second;
}
- pi.sig_en = sig_en;
- pi.sig_addr = port.addr;
- pi.sig_data = port.data;
-
bram_port_i++;
goto mapped_wr_port;
}
@@ -650,10 +569,6 @@ grow_read_ports:;
for (auto &pi : portinfos) {
if (pi.wrmode == 0) {
pi.mapped_port = -1;
- pi.sig_clock = SigBit();
- pi.sig_addr = SigSpec();
- pi.sig_data = SigSpec();
- pi.sig_en = SigSpec();
pi.make_outreg = false;
pi.make_transp = false;
}
@@ -685,10 +600,16 @@ grow_read_ports:;
for (int cell_port_i = 0; cell_port_i < GetSize(mem.rd_ports); cell_port_i++)
{
auto &port = mem.rd_ports[cell_port_i];
- bool transp = port.transparent;
-
- if (mem.wr_ports.empty())
- transp = false;
+ bool transp = false;
+ bool non_transp = false;
+
+ if (port.clk_enable) {
+ for (int i = 0; i < GetSize(mem.wr_ports); i++)
+ if (port.transparency_mask[i])
+ transp = true;
+ else if (!port.collision_x_mask[i])
+ non_transp = true;
+ }
pair<SigBit, bool> clkdom(port.clk, port.clk_polarity);
if (!port.clk_enable)
@@ -723,21 +644,13 @@ grow_read_ports:;
log(" Bram port %c%d.%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
goto skip_bram_rport;
}
- if (port.en != State::S1 && pi.enable == 0) {
- log(" Bram port %c%d.%d has no read enable input.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
+ if (non_transp && read_transp.count(pi.transp) && read_transp.at(pi.transp)) {
+ log(" Bram port %c%d.%d has incompatible read transparency.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
goto skip_bram_rport;
}
- skip_bram_rport_clkcheck:
- if (read_transp.count(pi.transp) && read_transp.at(pi.transp) != transp) {
- if (match.make_transp && GetSize(mem.wr_ports) <= 1) {
+ if (transp && (non_transp || (read_transp.count(pi.transp) && !read_transp.at(pi.transp)))) {
+ if (match.make_transp) {
pi.make_transp = true;
- if (pi.clocks != 0) {
- if (GetSize(mem.wr_ports) == 1 && wr_clkdom != clkdom) {
- log(" Bram port %c%d.%d cannot have soft transparency logic added as read and write clock domains differ.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
- goto skip_bram_rport;
- }
- enable_make_transp = true;
- }
} else {
log(" Bram port %c%d.%d has incompatible read transparency.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
goto skip_bram_rport;
@@ -750,22 +663,19 @@ grow_read_ports:;
}
}
+ skip_bram_rport_clkcheck:
log(" Mapped to bram port %c%d.%d.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
pi.mapped_port = cell_port_i;
- if (port.clk_enable) {
+ if (pi.clocks) {
clock_domains[pi.clocks] = clkdom;
clock_polarities[pi.clkpol] = clkdom.second;
- if (!pi.make_transp)
- read_transp[pi.transp] = transp;
- pi.sig_clock = clkdom.first;
- pi.sig_en = port.en;
- pi.effective_clkpol = clkdom.second;
+ if (non_transp)
+ read_transp[pi.transp] = false;
+ if (transp && !pi.make_transp)
+ read_transp[pi.transp] = true;
}
- pi.sig_addr = port.addr;
- pi.sig_data = port.data;
-
if (grow_read_ports_cursor < cell_port_i) {
grow_read_ports_cursor = cell_port_i;
try_growing_more_read_ports = true;
@@ -785,17 +695,19 @@ grow_read_ports:;
// update properties and re-check conditions
+ int dcells = GetSize(shuffle_map) / bram.dbits;
+ int acells = (mem.size + (1 << bram.abits) - 1) / (1 << bram.abits);
if (mode <= 1)
{
match_properties["dups"] = dup_count;
match_properties["waste"] = match_properties["dups"] * match_properties["bwaste"];
- int cells = ((mem.width + bram.dbits - 1) / bram.dbits) * ((mem.size + (1 << bram.abits) - 1) / (1 << bram.abits));
+ int cells = dcells * acells;
match_properties["efficiency"] = (100 * match_properties["bits"]) / (dup_count * cells * bram.dbits * (1 << bram.abits));
- match_properties["dcells"] = ((mem.width + bram.dbits - 1) / bram.dbits);
- match_properties["acells"] = ((mem.size + (1 << bram.abits) - 1) / (1 << bram.abits));
- match_properties["cells"] = match_properties["dcells"] * match_properties["acells"] * match_properties["dups"];
+ match_properties["dcells"] = dcells;
+ match_properties["acells"] = acells;
+ match_properties["cells"] = cells * dup_count;
log(" Updated properties: dups=%d waste=%d efficiency=%d\n",
match_properties["dups"], match_properties["waste"], match_properties["efficiency"]);
@@ -862,6 +774,90 @@ grow_read_ports:;
return true;
}
+ // At this point we are commited to replacing the RAM, and can mutate mem.
+
+ // Apply make_outreg and make_transp where necessary.
+ for (auto &pi : portinfos) {
+ if (pi.mapped_port == -1 || pi.wrmode)
+ continue;
+ auto &port = mem.rd_ports[pi.mapped_port];
+ if (pi.make_outreg) {
+ mem.extract_rdff(pi.mapped_port, initvals);
+ } else if (port.clk_enable) {
+ if (!pi.enable && port.en != State::S1)
+ mem.emulate_rden(pi.mapped_port, initvals);
+ else
+ mem.emulate_reset(pi.mapped_port, true, true, true, initvals);
+ }
+ if (pi.make_transp) {
+ for (int i = 0; i < GetSize(mem.wr_ports); i++)
+ if (port.transparency_mask[i])
+ mem.emulate_transparency(i, pi.mapped_port, initvals);
+ }
+ }
+
+ // We don't really support priorities, emulate them.
+ for (int i = 0; i < GetSize(mem.wr_ports); i++)
+ for (int j = 0; j < i; j++)
+ mem.emulate_priority(j, i, initvals);
+
+ // Swizzle the init data. Do this before changing mem.width, so that get_init_data works.
+ bool cell_init = !mem.inits.empty();
+ vector<Const> initdata;
+ if (cell_init) {
+ Const initparam = mem.get_init_data();
+ initdata.reserve(mem.size);
+ for (int i = 0; i < mem.size; i++) {
+ std::vector<State> val;
+ for (auto idx : shuffle_map) {
+ if (idx == -1)
+ val.push_back(State::Sx);
+ else
+ val.push_back(initparam[mem.width * i + idx]);
+ }
+ initdata.push_back(Const(val));
+ }
+ }
+
+ // Now the big swizzle.
+ mem.width = GetSize(shuffle_map);
+
+ // Swizzle write ports.
+ for (auto &port : mem.wr_ports) {
+ SigSpec new_en, new_data;
+ SigBit en_bit = State::S1;
+ for (auto idx : shuffle_map) {
+ if (idx == -1) {
+ new_data.append(State::Sx);
+ } else {
+ new_data.append(port.data[idx]);
+ en_bit = port.en[idx];
+ }
+ new_en.append(en_bit);
+ }
+ port.en = new_en;
+ port.data = new_data;
+ }
+
+ // Swizzle read ports.
+ for (auto &port : mem.rd_ports) {
+ SigSpec new_data = module->addWire(NEW_ID, mem.width);
+ Const new_init_value = Const(State::Sx, mem.width);
+ Const new_arst_value = Const(State::Sx, mem.width);
+ Const new_srst_value = Const(State::Sx, mem.width);
+ for (int i = 0; i < mem.width; i++)
+ if (shuffle_map[i] != -1) {
+ module->connect(port.data[shuffle_map[i]], new_data[i]);
+ new_init_value[i] = port.init_value[shuffle_map[i]];
+ new_arst_value[i] = port.arst_value[shuffle_map[i]];
+ new_srst_value[i] = port.srst_value[shuffle_map[i]];
+ }
+ port.data = new_data;
+ port.init_value = new_init_value;
+ port.arst_value = new_arst_value;
+ port.srst_value = new_srst_value;
+ }
+
// prepare variant parameters
dict<IdString, Const> variant_params;
@@ -872,21 +868,9 @@ grow_read_ports:;
dict<SigSpec, pair<SigSpec, SigSpec>> dout_cache;
- for (int grid_d = 0; grid_d*bram.dbits < mem.width; grid_d++)
+ for (int grid_d = 0; grid_d < dcells; grid_d++)
{
- SigSpec mktr_wraddr, mktr_wrdata, mktr_wrdata_q;
- vector<SigSpec> mktr_wren;
-
- if (enable_make_transp) {
- mktr_wraddr = module->addWire(NEW_ID, bram.abits);
- mktr_wrdata = module->addWire(NEW_ID, bram.dbits);
- mktr_wrdata_q = module->addWire(NEW_ID, bram.dbits);
- module->addDff(NEW_ID, make_transp_clk.first, mktr_wrdata, mktr_wrdata_q, make_transp_clk.second);
- for (int grid_a = 0; grid_a*(1 << bram.abits) < mem.size; grid_a++)
- mktr_wren.push_back(module->addWire(NEW_ID, make_transp_enbits));
- }
-
- for (int grid_a = 0; grid_a*(1 << bram.abits) < mem.size; grid_a++)
+ for (int grid_a = 0; grid_a < acells; grid_a++)
for (int dupidx = 0; dupidx < dup_count; dupidx++)
{
Cell *c = module->addCell(module->uniquify(stringf("%s.%d.%d.%d", mem.memid.c_str(), grid_d, grid_a, dupidx)), bram.name);
@@ -896,18 +880,16 @@ grow_read_ports:;
c->setParam(vp.first, vp.second);
if (cell_init) {
- int init_offset = grid_a*(1 << bram.abits);
+ int init_offset = grid_a*(1 << bram.abits) - mem.start_offset;
int init_shift = grid_d*bram.dbits;
int init_size = (1 << bram.abits);
Const initparam(State::Sx, init_size*bram.dbits);
- for (int i = 0; i < init_size; i++) {
- State padding = State::Sx;
+ for (int i = 0; i < init_size; i++)
for (int j = 0; j < bram.dbits; j++)
- if (init_offset+i < GetSize(initdata) && init_shift+j < GetSize(initdata[init_offset+i]))
+ if (init_offset+i < GetSize(initdata) && init_offset+i >= 0)
initparam[i*bram.dbits+j] = initdata[init_offset+i][init_shift+j];
else
- initparam[i*bram.dbits+j] = padding;
- }
+ initparam[i*bram.dbits+j] = State::Sx;
c->setParam(ID::INIT, initparam);
}
@@ -919,101 +901,84 @@ grow_read_ports:;
string prefix = stringf("%c%d", pi.group + 'A', pi.index + 1);
const char *pf = prefix.c_str();
- if (pi.clocks && (!c->hasPort(stringf("\\CLK%d", (pi.clocks-1) % clocks_max + 1)) || pi.sig_clock.wire)) {
- c->setPort(stringf("\\CLK%d", (pi.clocks-1) % clocks_max + 1), pi.sig_clock);
- if (pi.clkpol > 1 && pi.sig_clock.wire)
- c->setParam(stringf("\\CLKPOL%d", (pi.clkpol-1) % clkpol_max + 1), clock_polarities.at(pi.clkpol));
- if (pi.transp > 1 && pi.sig_clock.wire)
- c->setParam(stringf("\\TRANSP%d", (pi.transp-1) % transp_max + 1), read_transp.at(pi.transp));
- }
+ if (pi.clocks && clock_domains.count(pi.clocks))
+ c->setPort(stringf("\\CLK%d", (pi.clocks-1) % clocks_max + 1), clock_domains.at(pi.clocks).first);
+ if (pi.clkpol > 1 && clock_polarities.count(pi.clkpol))
+ c->setParam(stringf("\\CLKPOL%d", (pi.clkpol-1) % clkpol_max + 1), clock_polarities.at(pi.clkpol));
+ if (pi.transp > 1 && read_transp.count(pi.transp))
+ c->setParam(stringf("\\TRANSP%d", (pi.transp-1) % transp_max + 1), read_transp.at(pi.transp));
SigSpec addr_ok;
- if (GetSize(pi.sig_addr) > bram.abits) {
- SigSpec extra_addr = pi.sig_addr.extract(bram.abits, GetSize(pi.sig_addr) - bram.abits);
+ SigSpec sig_addr;
+ if (pi.mapped_port >= 0) {
+ if (pi.wrmode == 1)
+ sig_addr = mem.wr_ports[pi.mapped_port].addr;
+ else
+ sig_addr = mem.rd_ports[pi.mapped_port].addr;
+ }
+
+ if (GetSize(sig_addr) > bram.abits) {
+ SigSpec extra_addr = sig_addr.extract(bram.abits, GetSize(sig_addr) - bram.abits);
SigSpec extra_addr_sel = SigSpec(grid_a, GetSize(extra_addr));
addr_ok = module->Eq(NEW_ID, extra_addr, extra_addr_sel);
}
- if (pi.enable)
- {
- SigSpec sig_en = pi.sig_en;
+ sig_addr.extend_u0(bram.abits);
+ c->setPort(stringf("\\%sADDR", pf), sig_addr);
- if (pi.wrmode == 1) {
- sig_en.extend_u0((grid_d+1) * pi.enable);
- sig_en = sig_en.extract(grid_d * pi.enable, pi.enable);
+ if (pi.wrmode == 1) {
+ if (pi.mapped_port == -1)
+ {
+ if (pi.enable)
+ c->setPort(stringf("\\%sEN", pf), Const(State::S0, pi.enable));
+ continue;
}
- if (!addr_ok.empty())
- sig_en = module->Mux(NEW_ID, SigSpec(0, GetSize(sig_en)), sig_en, addr_ok);
-
- c->setPort(stringf("\\%sEN", pf), sig_en);
-
- if (pi.wrmode == 1 && enable_make_transp)
- module->connect(mktr_wren[grid_a], sig_en);
- }
+ auto &port = mem.wr_ports[pi.mapped_port];
+ SigSpec sig_data = port.data.extract(grid_d * bram.dbits, bram.dbits);
+ c->setPort(stringf("\\%sDATA", pf), sig_data);
- SigSpec sig_addr = pi.sig_addr;
- sig_addr.extend_u0(bram.abits);
- c->setPort(stringf("\\%sADDR", pf), sig_addr);
+ if (pi.enable)
+ {
+ SigSpec sig_en;
+ int stride = bram.dbits / pi.enable;
+ for (int i = 0; i < pi.enable; i++)
+ sig_en.append(port.en[stride * i + grid_d * bram.dbits]);
- if (pi.wrmode == 1 && enable_make_transp && grid_a == 0)
- module->connect(mktr_wraddr, sig_addr);
+ if (!addr_ok.empty())
+ sig_en = module->Mux(NEW_ID, SigSpec(0, GetSize(sig_en)), sig_en, addr_ok);
- SigSpec sig_data = pi.sig_data;
- sig_data.extend_u0((grid_d+1) * bram.dbits);
- sig_data = sig_data.extract(grid_d * bram.dbits, bram.dbits);
+ c->setPort(stringf("\\%sEN", pf), sig_en);
- if (pi.wrmode == 1) {
- c->setPort(stringf("\\%sDATA", pf), sig_data);
- if (enable_make_transp && grid_a == 0)
- module->connect(mktr_wrdata, sig_data);
+ }
} else {
- SigSpec bram_dout = module->addWire(NEW_ID, bram.dbits);
- c->setPort(stringf("\\%sDATA", pf), bram_dout);
- if (pi.make_outreg && pi.make_transp) {
- log(" Moving output register to address for transparent port %c%d.%d.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
- SigSpec sig_addr_q = module->addWire(NEW_ID, bram.abits);
- module->addDff(NEW_ID, pi.sig_clock, sig_addr, sig_addr_q, pi.effective_clkpol);
- c->setPort(stringf("\\%sADDR", pf), sig_addr_q);
- } else if (pi.make_outreg) {
- SigSpec bram_dout_q = module->addWire(NEW_ID, bram.dbits);
- if (!pi.sig_en.empty())
- bram_dout = module->Mux(NEW_ID, bram_dout_q, bram_dout, pi.sig_en);
- module->addDff(NEW_ID, pi.sig_clock, bram_dout, bram_dout_q, pi.effective_clkpol);
- bram_dout = bram_dout_q;
- } else if (pi.make_transp) {
- log(" Adding extra logic for transparent port %c%d.%d.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
-
- SigSpec transp_en_d = module->Mux(NEW_ID, SigSpec(0, make_transp_enbits),
- mktr_wren[grid_a], module->Eq(NEW_ID, mktr_wraddr, sig_addr));
-
- SigSpec transp_en_q = module->addWire(NEW_ID, make_transp_enbits);
- module->addDff(NEW_ID, make_transp_clk.first, transp_en_d, transp_en_q, make_transp_clk.second);
-
- for (int i = 0; i < make_transp_enbits; i++) {
- int en_width = bram.dbits / make_transp_enbits;
- SigSpec orig_bram_dout = bram_dout.extract(i * en_width, en_width);
- SigSpec bypass_dout = mktr_wrdata_q.extract(i * en_width, en_width);
- bram_dout.replace(i * en_width, module->Mux(NEW_ID, orig_bram_dout, bypass_dout, transp_en_q[i]));
- }
+ if (pi.mapped_port == -1)
+ {
+ if (pi.enable)
+ c->setPort(stringf("\\%sEN", pf), State::S0);
+ continue;
}
+ auto &port = mem.rd_ports[pi.mapped_port];
+ SigSpec sig_data = port.data.extract(grid_d * bram.dbits, bram.dbits);
- for (int i = bram.dbits-1; i >= 0; i--)
- if (sig_data[i].wire == nullptr) {
- sig_data.remove(i);
- bram_dout.remove(i);
- }
+ SigSpec bram_dout = module->addWire(NEW_ID, bram.dbits);
+ c->setPort(stringf("\\%sDATA", pf), bram_dout);
SigSpec addr_ok_q = addr_ok;
- if ((pi.clocks || pi.make_outreg) && !addr_ok.empty()) {
+ if (port.clk_enable && !addr_ok.empty()) {
addr_ok_q = module->addWire(NEW_ID);
- if (!pi.sig_en.empty())
- addr_ok = module->Mux(NEW_ID, addr_ok_q, addr_ok, pi.sig_en);
- module->addDff(NEW_ID, pi.sig_clock, addr_ok, addr_ok_q, pi.effective_clkpol);
+ module->addDffe(NEW_ID, port.clk, port.en, addr_ok, addr_ok_q, port.clk_polarity);
}
dout_cache[sig_data].first.append(addr_ok_q);
dout_cache[sig_data].second.append(bram_dout);
+
+ if (pi.enable) {
+ SigSpec sig_en = port.en;
+ if (!addr_ok.empty())
+ sig_en = module->And(NEW_ID, sig_en, addr_ok);
+ c->setPort(stringf("\\%sEN", pf), sig_en);
+ }
}
}
}
@@ -1037,9 +1002,10 @@ grow_read_ports:;
return true;
}
-void handle_memory(Mem &mem, const rules_t &rules)
+void handle_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals)
{
log("Processing %s.%s:\n", log_id(mem.module), log_id(mem.memid));
+ mem.narrow();
bool cell_init = !mem.inits.empty();
@@ -1189,7 +1155,7 @@ void handle_memory(Mem &mem, const rules_t &rules)
if (or_next_if_better && i+1 == GetSize(rules.matches) && vi+1 == GetSize(rules.brams.at(match.name)))
log_error("Found 'or_next_if_better' in last match rule.\n");
- if (!replace_memory(mem, rules, bram, match, match_properties, 1)) {
+ if (!replace_memory(mem, rules, initvals, bram, match, match_properties, 1)) {
log(" Mapping to bram type %s failed.\n", log_id(match.name));
failed_brams.insert(pair<IdString, int>(bram.name, bram.variant));
goto next_match_rule;
@@ -1216,12 +1182,12 @@ void handle_memory(Mem &mem, const rules_t &rules)
best_rule_cache.clear();
auto &best_bram = rules.brams.at(rules.matches.at(best_rule.first).name).at(best_rule.second);
- if (!replace_memory(mem, rules, best_bram, rules.matches.at(best_rule.first), match_properties, 2))
+ if (!replace_memory(mem, rules, initvals, best_bram, rules.matches.at(best_rule.first), match_properties, 2))
log_error("Mapping to bram type %s (variant %d) after pre-selection failed.\n", log_id(best_bram.name), best_bram.variant);
return;
}
- if (!replace_memory(mem, rules, bram, match, match_properties, 0)) {
+ if (!replace_memory(mem, rules, initvals, bram, match, match_properties, 0)) {
log(" Mapping to bram type %s failed.\n", log_id(match.name));
failed_brams.insert(pair<IdString, int>(bram.name, bram.variant));
goto next_match_rule;
@@ -1353,9 +1319,12 @@ struct MemoryBramPass : public Pass {
}
extra_args(args, argidx, design);
- for (auto mod : design->selected_modules())
- for (auto &mem : Mem::get_selected_memories(mod))
- handle_memory(mem, rules);
+ for (auto mod : design->selected_modules()) {
+ SigMap sigmap(mod);
+ FfInitVals initvals(&sigmap, mod);
+ for (auto &mem : Mem::get_selected_memories(mod))
+ handle_memory(mem, rules, &initvals);
+ }
}
} MemoryBramPass;
diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc
index ede6ca6a1..bf3bb34f8 100644
--- a/passes/memory/memory_collect.cc
+++ b/passes/memory/memory_collect.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc
index 4adcb462e..91209d428 100644
--- a/passes/memory/memory_dff.cc
+++ b/passes/memory/memory_dff.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -17,415 +17,627 @@
*
*/
-#include <algorithm>
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/modtools.h"
#include "kernel/ffinit.h"
+#include "kernel/qcsat.h"
+#include "kernel/mem.h"
+#include "kernel/ff.h"
+#include "kernel/ffmerge.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-struct MemoryDffWorker
+struct MuxData {
+ int base_idx;
+ int size;
+ bool is_b;
+ SigSpec sig_s;
+ std::vector<SigSpec> sig_other;
+};
+
+struct PortData {
+ bool relevant;
+ std::vector<bool> uncollidable_mask;
+ std::vector<bool> transparency_mask;
+ std::vector<bool> collision_x_mask;
+ bool final_transparency;
+ bool final_collision_x;
+};
+
+// A helper with some caching for transparency-related SAT queries.
+// Bound to a single memory read port in the process of being converted
+// from async to sync..
+struct MemQueryCache
{
- Module *module;
- SigMap sigmap;
+ QuickConeSat &qcsat;
+ // The memory.
+ Mem &mem;
+ // The port, still async at this point.
+ MemRd &port;
+ // The virtual FF that will end up merged into this port.
+ FfData &ff;
+ // An ezSAT variable that is true when we actually care about the data
+ // read from memory (ie. the FF has enable on and is not in reset).
+ int port_ren;
+ // Some caches.
+ dict<std::pair<int, SigBit>, bool> cache_can_collide_rdwr;
+ dict<std::tuple<int, int, SigBit, SigBit>, bool> cache_can_collide_together;
+ dict<std::tuple<int, SigBit, SigBit, bool>, bool> cache_is_w2rbyp;
+ dict<std::tuple<SigBit, bool>, bool> cache_impossible_with_ren;
+
+ MemQueryCache(QuickConeSat &qcsat, Mem &mem, MemRd &port, FfData &ff) : qcsat(qcsat), mem(mem), port(port), ff(ff) {
+ // port_ren is an upper bound on when we care about the value fetched
+ // from memory this cycle.
+ int ren = ezSAT::CONST_TRUE;
+ if (ff.has_ce) {
+ ren = qcsat.importSigBit(ff.sig_ce);
+ if (!ff.pol_ce)
+ ren = qcsat.ez->NOT(ren);
+ }
+ if (ff.has_srst) {
+ int nrst = qcsat.importSigBit(ff.sig_srst);
+ if (ff.pol_srst)
+ nrst = qcsat.ez->NOT(nrst);
+ ren = qcsat.ez->AND(ren, nrst);
+ }
+ port_ren = ren;
+ }
- vector<Cell*> dff_cells;
- dict<SigBit, SigBit> invbits;
- dict<SigBit, int> sigbit_users_count;
- dict<SigSpec, Cell*> mux_cells_a, mux_cells_b;
- pool<Cell*> forward_merged_dffs, candidate_dffs;
- FfInitVals initvals;
+ // Returns ezSAT variable that is true iff the two addresses are the same.
+ int addr_eq(SigSpec raddr, SigSpec waddr) {
+ int abits = std::max(GetSize(raddr), GetSize(waddr));
+ raddr.extend_u0(abits);
+ waddr.extend_u0(abits);
+ return qcsat.ez->vec_eq(qcsat.importSig(raddr), qcsat.importSig(waddr));
+ }
- MemoryDffWorker(Module *module) : module(module), sigmap(module)
- {
- initvals.set(&sigmap, module);
+ // Returns true if a given write port bit can be active at the same time
+ // as this read port and at the same address.
+ bool can_collide_rdwr(int widx, SigBit wen) {
+ std::pair<int, SigBit> key(widx, wen);
+ auto it = cache_can_collide_rdwr.find(key);
+ if (it != cache_can_collide_rdwr.end())
+ return it->second;
+ auto &wport = mem.wr_ports[widx];
+ int aeq = addr_eq(port.addr, wport.addr);
+ int wen_sat = qcsat.importSigBit(wen);
+ qcsat.prepare();
+ bool res = qcsat.ez->solve(aeq, wen_sat, port_ren);
+ cache_can_collide_rdwr[key] = res;
+ return res;
}
- bool find_sig_before_dff(RTLIL::SigSpec &sig, RTLIL::SigSpec &clk, bool &clk_polarity)
- {
- sigmap.apply(sig);
+ // Returns true if both given write port bits can be active at the same
+ // time as this read port and at the same address (three-way collision).
+ bool can_collide_together(int widx1, int widx2, int bitidx) {
+ auto &wport1 = mem.wr_ports[widx1];
+ auto &wport2 = mem.wr_ports[widx2];
+ SigBit wen1 = wport1.en[bitidx];
+ SigBit wen2 = wport2.en[bitidx];
+ std::tuple<int, int, SigBit, SigBit> key(widx1, widx2, wen1, wen2);
+ auto it = cache_can_collide_together.find(key);
+ if (it != cache_can_collide_together.end())
+ return it->second;
+ int aeq1 = addr_eq(port.addr, wport1.addr);
+ int aeq2 = addr_eq(port.addr, wport2.addr);
+ int wen1_sat = qcsat.importSigBit(wen1);
+ int wen2_sat = qcsat.importSigBit(wen2);
+ qcsat.prepare();
+ bool res = qcsat.ez->solve(wen1_sat, wen2_sat, aeq1, aeq2, port_ren);
+ cache_can_collide_together[key] = res;
+ return res;
+ }
- dict<SigBit, SigBit> cache;
+ // Returns true if the given mux selection signal is a valid data-bypass
+ // signal in soft transparency logic for a given write port bit.
+ bool is_w2rbyp(int widx, SigBit wen, SigBit sel, bool neg_sel) {
+ std::tuple<int, SigBit, SigBit, bool> key(widx, wen, sel, neg_sel);
+ auto it = cache_is_w2rbyp.find(key);
+ if (it != cache_is_w2rbyp.end())
+ return it->second;
+ auto &wport = mem.wr_ports[widx];
+ int aeq = addr_eq(port.addr, wport.addr);
+ int wen_sat = qcsat.importSigBit(wen);
+ int sel_expected = qcsat.ez->AND(aeq, wen_sat);
+ int sel_sat = qcsat.importSigBit(sel);
+ if (neg_sel)
+ sel_sat = qcsat.ez->NOT(sel_sat);
+ qcsat.prepare();
+ bool res = !qcsat.ez->solve(port_ren, qcsat.ez->XOR(sel_expected, sel_sat));
+ cache_is_w2rbyp[key] = res;
+ return res;
+ }
- for (auto &bit : sig)
- {
- if (cache.count(bit)) {
- bit = cache[bit];
- continue;
- }
+ // Returns true if the given mux selection signal can never be true
+ // when this port is active.
+ bool impossible_with_ren(SigBit sel, bool neg_sel) {
+ std::tuple<SigBit, bool> key(sel, neg_sel);
+ auto it = cache_impossible_with_ren.find(key);
+ if (it != cache_impossible_with_ren.end())
+ return it->second;
+ int sel_sat = qcsat.importSigBit(sel);
+ if (neg_sel)
+ sel_sat = qcsat.ez->NOT(sel_sat);
+ qcsat.prepare();
+ bool res = !qcsat.ez->solve(port_ren, sel_sat);
+ cache_impossible_with_ren[key] = res;
+ return res;
+ }
- if (bit.wire == NULL)
- continue;
+ // Helper for data_eq: walks up a multiplexer when the value of its
+ // sel signal is constant under the assumption that this read port
+ // is active and a given other mux sel signal is true.
+ bool walk_up_mux_cond(SigBit sel, bool neg_sel, SigBit &bit) {
+ auto &drivers = qcsat.modwalker.signal_drivers[qcsat.modwalker.sigmap(bit)];
+ if (GetSize(drivers) != 1)
+ return false;
+ auto driver = *drivers.begin();
+ if (!driver.cell->type.in(ID($mux), ID($pmux)))
+ return false;
+ log_assert(driver.port == ID::Y);
+ SigSpec sig_s = driver.cell->getPort(ID::S);
+ int sel_sat = qcsat.importSigBit(sel);
+ if (neg_sel)
+ sel_sat = qcsat.ez->NOT(sel_sat);
+ bool all_0 = true;
+ int width = driver.cell->parameters.at(ID::WIDTH).as_int();
+ for (int i = 0; i < GetSize(sig_s); i++) {
+ int sbit = qcsat.importSigBit(sig_s[i]);
+ qcsat.prepare();
+ if (!qcsat.ez->solve(port_ren, sel_sat, qcsat.ez->NOT(sbit))) {
+ bit = driver.cell->getPort(ID::B)[i * width + driver.offset];
+ return true;
+ }
+ if (qcsat.ez->solve(port_ren, sel_sat, sbit))
+ all_0 = false;
+ }
+ if (all_0) {
+ bit = driver.cell->getPort(ID::A)[driver.offset];
+ return true;
+ }
+ return false;
+ }
- if (initvals(bit) != State::Sx)
- return false;
+ // Returns true if a given data signal is equivalent to another, under
+ // the assumption that this read port is active and a given mux sel signal
+ // is true. Used to match transparency logic data with write port data.
+ // The walk_up_mux_cond part is necessary because write ports in yosys
+ // tend to be connected to things like (wen ? wdata : 'x).
+ bool data_eq(SigBit sel, bool neg_sel, SigBit dbit, SigBit odbit) {
+ if (qcsat.modwalker.sigmap(dbit) == qcsat.modwalker.sigmap(odbit))
+ return true;
+ while (walk_up_mux_cond(sel, neg_sel, dbit));
+ while (walk_up_mux_cond(sel, neg_sel, odbit));
+ return qcsat.modwalker.sigmap(dbit) == qcsat.modwalker.sigmap(odbit);
+ }
+};
- for (auto cell : dff_cells)
- {
- SigSpec this_clk = cell->getPort(ID::CLK);
- bool this_clk_polarity = cell->parameters[ID::CLK_POLARITY].as_bool();
+struct MemoryDffWorker
+{
+ Module *module;
+ ModWalker modwalker;
+ FfInitVals initvals;
+ FfMergeHelper merger;
- if (invbits.count(this_clk)) {
- this_clk = invbits.at(this_clk);
- this_clk_polarity = !this_clk_polarity;
- }
+ MemoryDffWorker(Module *module) : module(module), modwalker(module->design)
+ {
+ modwalker.setup(module);
+ initvals.set(&modwalker.sigmap, module);
+ merger.set(&initvals, module);
+ }
- if (clk != RTLIL::SigSpec(RTLIL::State::Sx)) {
- if (this_clk != clk)
+ // Starting from the output of an async read port, as long as the data
+ // signal's only user is a mux data signal, passes through the mux
+ // and remembers information about it. Conceptually works on every
+ // bit separately, but coalesces the result when possible.
+ SigSpec walk_muxes(SigSpec data, std::vector<MuxData> &res) {
+ bool did_something;
+ do {
+ did_something = false;
+ int prev_idx = -1;
+ Cell *prev_cell = nullptr;
+ bool prev_is_b = false;
+ for (int i = 0; i < GetSize(data); i++) {
+ SigBit bit = modwalker.sigmap(data[i]);
+ auto &consumers = modwalker.signal_consumers[bit];
+ if (GetSize(consumers) != 1 || modwalker.signal_outputs.count(bit))
+ continue;
+ auto consumer = *consumers.begin();
+ bool is_b;
+ if (consumer.cell->type == ID($mux)) {
+ if (consumer.port == ID::A) {
+ is_b = false;
+ } else if (consumer.port == ID::B) {
+ is_b = true;
+ } else {
continue;
- if (this_clk_polarity != clk_polarity)
+ }
+ } else if (consumer.cell->type == ID($pmux)) {
+ if (consumer.port == ID::A) {
+ is_b = false;
+ } else {
continue;
- }
-
- RTLIL::SigSpec q_norm = cell->getPort(ID::Q);
- sigmap.apply(q_norm);
-
- RTLIL::SigSpec d = q_norm.extract(bit, &cell->getPort(ID::D));
- if (d.size() != 1)
+ }
+ } else {
continue;
-
- if (cell->type == ID($sdffce)) {
- SigSpec rval = cell->parameters[ID::SRST_VALUE];
- SigSpec rbit = q_norm.extract(bit, &rval);
- if (cell->parameters[ID::SRST_POLARITY].as_bool())
- d = module->Mux(NEW_ID, d, rbit, cell->getPort(ID::SRST));
- else
- d = module->Mux(NEW_ID, rbit, d, cell->getPort(ID::SRST));
}
-
- if (cell->type.in(ID($dffe), ID($sdffe), ID($sdffce))) {
- if (cell->parameters[ID::EN_POLARITY].as_bool())
- d = module->Mux(NEW_ID, bit, d, cell->getPort(ID::EN));
- else
- d = module->Mux(NEW_ID, d, bit, cell->getPort(ID::EN));
+ SigSpec y = consumer.cell->getPort(ID::Y);
+ int mux_width = GetSize(y);
+ SigBit ybit = y.extract(consumer.offset);
+ if (prev_cell != consumer.cell || prev_idx+1 != i || prev_is_b != is_b) {
+ MuxData md;
+ md.base_idx = i;
+ md.size = 0;
+ md.is_b = is_b;
+ md.sig_s = consumer.cell->getPort(ID::S);
+ md.sig_other.resize(GetSize(md.sig_s));
+ prev_cell = consumer.cell;
+ prev_is_b = is_b;
+ res.push_back(md);
}
-
- if (cell->type.in(ID($sdff), ID($sdffe))) {
- SigSpec rval = cell->parameters[ID::SRST_VALUE];
- SigSpec rbit = q_norm.extract(bit, &rval);
- if (cell->parameters[ID::SRST_POLARITY].as_bool())
- d = module->Mux(NEW_ID, d, rbit, cell->getPort(ID::SRST));
- else
- d = module->Mux(NEW_ID, rbit, d, cell->getPort(ID::SRST));
+ auto &md = res.back();
+ md.size++;
+ for (int j = 0; j < GetSize(md.sig_s); j++) {
+ SigBit obit = consumer.cell->getPort(is_b ? ID::A : ID::B).extract(j * mux_width + consumer.offset);
+ md.sig_other[j].append(obit);
}
-
- cache[bit] = d;
- bit = d;
- clk = this_clk;
- clk_polarity = this_clk_polarity;
- candidate_dffs.insert(cell);
- goto replaced_this_bit;
+ prev_idx = i;
+ data[i] = ybit;
+ did_something = true;
}
-
- return false;
- replaced_this_bit:;
- }
-
- return true;
+ } while (did_something);
+ return data;
}
- bool find_sig_after_dffe(RTLIL::SigSpec &sig, RTLIL::SigSpec &clk, bool &clk_polarity, RTLIL::SigSpec &en, bool &en_polarity)
+ // Merges FF and possibly soft transparency logic into an asynchronous
+ // read port, making it into a synchronous one.
+ //
+ // There are three moving parts involved here:
+ //
+ // - the async port, which we start from, whose data port is input to...
+ // - an arbitrary chain of $mux and $pmux cells implementing soft transparency
+ // logic (ie. bypassing write port's data iff the write port is active and
+ // writing to the same address as this read port), which in turn feeds...
+ // - a final FF
+ //
+ // The async port and the mux chain are not allowed to have any users that
+ // are not part of the above.
+ //
+ // The algorithm is:
+ //
+ // 1. Walk through the muxes.
+ // 2. Recognize the final FF.
+ // 3. Knowing the FF's clock and read enable, make a list of write ports
+ // that we'll run transparency analysis on.
+ // 4. For every mux bit, recognize it as one of:
+ // - a transparency bypass mux for some port
+ // - a bypass mux that feeds 'x instead (this will result in collision
+ // don't care behavior being recognized)
+ // - a mux that never selects the other value when read port is active,
+ // and can thus be skipped (this is necessary because this could
+ // be a transparency bypass mux for never-colliding port that other
+ // passes failed to optimize)
+ // - a mux whose other input is 'x, and can thus be skipped
+ // 5. When recognizing transparency bypasses, take care to preserve priority
+ // behavior — when two bypasses are sequential muxes on the chain, they
+ // effectively have priority over one another, and the transform can
+ // only be performed when either a) their corresponding write ports
+ // also have priority, or b) there can never be a three-way collision
+ // between the two write ports and the read port.
+ // 6. Check consistency of per-bit transparency masks, merge them into
+ // per-port transparency masks
+ // 7. If everything went fine in the previous steps, actually perform
+ // the merge.
+ void handle_rd_port(Mem &mem, QuickConeSat &qcsat, int idx)
{
- sigmap.apply(sig);
-
- for (auto &bit : sig)
- {
- if (bit.wire == NULL)
- continue;
-
- for (auto cell : dff_cells)
- {
- if (forward_merged_dffs.count(cell))
- continue;
- if (!cell->type.in(ID($dff), ID($dffe)))
- continue;
-
- SigSpec this_clk = cell->getPort(ID::CLK);
- bool this_clk_polarity = cell->parameters[ID::CLK_POLARITY].as_bool();
- SigSpec this_en = State::S1;
- bool this_en_polarity = true;
-
- if (cell->type == ID($dffe)) {
- this_en = cell->getPort(ID::EN);
- this_en_polarity = cell->parameters[ID::EN_POLARITY].as_bool();
- }
-
- if (invbits.count(this_clk)) {
- this_clk = invbits.at(this_clk);
- this_clk_polarity = !this_clk_polarity;
- }
+ auto &port = mem.rd_ports[idx];
+ log("Checking read port `%s'[%d] in module `%s': ", mem.memid.c_str(), idx, module->name.c_str());
+
+ std::vector<MuxData> muxdata;
+ SigSpec data = walk_muxes(port.data, muxdata);
+ FfData ff;
+ pool<std::pair<Cell *, int>> bits;
+ if (!merger.find_output_ff(data, ff, bits)) {
+ log("no output FF found.\n");
+ return;
+ }
+ if (!ff.has_clk) {
+ log("output latches are not supported.\n");
+ return;
+ }
+ if (ff.has_aload) {
+ log("output FF has async load, not supported.\n");
+ return;
+ }
+ if (ff.has_sr) {
+ // Latches and FFs with SR are not supported.
+ log("output FF has both set and reset, not supported.\n");
+ return;
+ }
- if (invbits.count(this_en)) {
- this_en = invbits.at(this_en);
- this_en_polarity = !this_en_polarity;
+ // Construct cache.
+ MemQueryCache cache(qcsat, mem, port, ff);
+
+ // Prepare information structure about all ports, recognize port bits
+ // that can never collide at all and don't need to be checked.
+ std::vector<PortData> portdata;
+ for (int i = 0; i < GetSize(mem.wr_ports); i++) {
+ PortData pd;
+ auto &wport = mem.wr_ports[i];
+ pd.relevant = true;
+ if (!wport.clk_enable)
+ pd.relevant = false;
+ if (wport.clk != ff.sig_clk)
+ pd.relevant = false;
+ if (wport.clk_polarity != ff.pol_clk)
+ pd.relevant = false;
+ // In theory, we *could* support mismatched width
+ // ports here. However, it's not worth it — wide
+ // ports are recognized *after* memory_dff in
+ // a normal flow.
+ if (wport.wide_log2 != port.wide_log2)
+ pd.relevant = false;
+ pd.uncollidable_mask.resize(GetSize(port.data));
+ pd.transparency_mask.resize(GetSize(port.data));
+ pd.collision_x_mask.resize(GetSize(port.data));
+ if (pd.relevant) {
+ // If we got this far, this port is potentially
+ // transparent and/or has undefined collision
+ // behavior. Now, for every bit, check if it can
+ // ever collide.
+ for (int j = 0; j < ff.width; j++) {
+ if (!cache.can_collide_rdwr(i, wport.en[j])) {
+ pd.uncollidable_mask[j] = true;
+ pd.collision_x_mask[j] = true;
+ }
}
+ }
+ portdata.push_back(pd);
+ }
- if (clk != RTLIL::SigSpec(RTLIL::State::Sx)) {
- if (this_clk != clk)
- continue;
- if (this_clk_polarity != clk_polarity)
- continue;
- if (this_en != en)
- continue;
- if (this_en_polarity != en_polarity)
- continue;
+ // Now inspect the mux chain.
+ for (auto &md : muxdata) {
+ // We only mark transparent bits after processing a complete
+ // mux, so that the transparency priority validation check
+ // below sees transparency information as of previous mux.
+ std::vector<std::pair<PortData&, int>> trans_queue;
+ for (int sel_idx = 0; sel_idx < GetSize(md.sig_s); sel_idx++) {
+ SigBit sbit = md.sig_s[sel_idx];
+ SigSpec &odata = md.sig_other[sel_idx];
+ for (int bitidx = md.base_idx; bitidx < md.base_idx+md.size; bitidx++) {
+ SigBit odbit = odata[bitidx-md.base_idx];
+ bool recognized = false;
+ for (int pi = 0; pi < GetSize(mem.wr_ports); pi++) {
+ auto &pd = portdata[pi];
+ auto &wport = mem.wr_ports[pi];
+ if (!pd.relevant)
+ continue;
+ if (pd.uncollidable_mask[bitidx])
+ continue;
+ bool match = cache.is_w2rbyp(pi, wport.en[bitidx], sbit, md.is_b);
+ if (!match)
+ continue;
+ // If we got here, we recognized this mux sel
+ // as valid bypass sel for a given port bit.
+ if (odbit == State::Sx) {
+ // 'x, mark collision don't care.
+ pd.collision_x_mask[bitidx] = true;
+ pd.transparency_mask[bitidx] = false;
+ } else if (cache.data_eq(sbit, md.is_b, wport.data[bitidx], odbit)) {
+ // Correct data value, mark transparency,
+ // but only after verifying that priority
+ // is fine.
+ for (int k = 0; k < GetSize(mem.wr_ports); k++) {
+ if (portdata[k].transparency_mask[bitidx]) {
+ if (wport.priority_mask[k])
+ continue;
+ if (!cache.can_collide_together(pi, k, bitidx))
+ continue;
+ log("FF found, but transparency logic priority doesn't match write priority.\n");
+ return;
+ }
+ }
+ recognized = true;
+ trans_queue.push_back({pd, bitidx});
+ break;
+ } else {
+ log("FF found, but with a mux data input that doesn't seem to correspond to transparency logic.\n");
+ return;
+ }
+ }
+ if (!recognized) {
+ // If we haven't positively identified this as
+ // a bypass: it's still skippable if the
+ // data is 'x, or if the sel cannot actually be
+ // active.
+ if (odbit == State::Sx)
+ continue;
+ if (cache.impossible_with_ren(sbit, md.is_b))
+ continue;
+ log("FF found, but with a mux select that doesn't seem to correspond to transparency logic.\n");
+ return;
+ }
}
+ }
+ // Done with this mux, now actually apply the transparencies.
+ for (auto it : trans_queue) {
+ it.first.transparency_mask[it.second] = true;
+ it.first.collision_x_mask[it.second] = false;
+ }
+ }
- RTLIL::SigSpec q_norm = cell->getPort(ID::D);
- sigmap.apply(q_norm);
-
- RTLIL::SigSpec d = q_norm.extract(bit, &cell->getPort(ID::Q));
- if (d.size() != 1)
+ // Final merging and validation of per-bit masks.
+ for (int pi = 0; pi < GetSize(mem.wr_ports); pi++) {
+ auto &pd = portdata[pi];
+ if (!pd.relevant)
+ continue;
+ bool trans = false;
+ bool non_trans = false;
+ for (int i = 0; i < ff.width; i++) {
+ if (pd.collision_x_mask[i])
continue;
-
- if (initvals(d) != State::Sx)
- return false;
-
- bit = d;
- clk = this_clk;
- clk_polarity = this_clk_polarity;
- en = this_en;
- en_polarity = this_en_polarity;
- candidate_dffs.insert(cell);
- goto replaced_this_bit;
+ if (pd.transparency_mask[i])
+ trans = true;
+ else
+ non_trans = true;
}
-
- return false;
- replaced_this_bit:;
+ if (trans && non_trans) {
+ log("FF found, but soft transparency logic is inconsistent for port %d.\n", pi);
+ return;
+ }
+ pd.final_transparency = trans;
+ pd.final_collision_x = !trans && !non_trans;
}
- return true;
+ // OK, it worked.
+ log("merging output FF to cell.\n");
+
+ merger.remove_output_ff(bits);
+ if (ff.has_ce && !ff.pol_ce)
+ ff.sig_ce = module->LogicNot(NEW_ID, ff.sig_ce);
+ if (ff.has_arst && !ff.pol_arst)
+ ff.sig_arst = module->LogicNot(NEW_ID, ff.sig_arst);
+ if (ff.has_srst && !ff.pol_srst)
+ ff.sig_srst = module->LogicNot(NEW_ID, ff.sig_srst);
+ port.clk = ff.sig_clk;
+ port.clk_enable = true;
+ port.clk_polarity = ff.pol_clk;
+ if (ff.has_ce)
+ port.en = ff.sig_ce;
+ else
+ port.en = State::S1;
+ if (ff.has_arst) {
+ port.arst = ff.sig_arst;
+ port.arst_value = ff.val_arst;
+ } else {
+ port.arst = State::S0;
+ }
+ if (ff.has_srst) {
+ port.srst = ff.sig_srst;
+ port.srst_value = ff.val_srst;
+ port.ce_over_srst = ff.ce_over_srst;
+ } else {
+ port.srst = State::S0;
+ }
+ port.init_value = ff.val_init;
+ port.data = ff.sig_q;
+ for (int pi = 0; pi < GetSize(mem.wr_ports); pi++) {
+ auto &pd = portdata[pi];
+ if (!pd.relevant)
+ continue;
+ if (pd.final_collision_x) {
+ log(" Write port %d: don't care on collision.\n", pi);
+ port.collision_x_mask[pi] = true;
+ } else if (pd.final_transparency) {
+ log(" Write port %d: transparent.\n", pi);
+ port.transparency_mask[pi] = true;
+ } else {
+ log(" Write port %d: non-transparent.\n", pi);
+ }
+ }
+ mem.emit();
}
- void handle_wr_cell(RTLIL::Cell *cell)
+ void handle_rd_port_addr(Mem &mem, int idx)
{
- log("Checking cell `%s' in module `%s': ", cell->name.c_str(), module->name.c_str());
+ auto &port = mem.rd_ports[idx];
+ log("Checking read port address `%s'[%d] in module `%s': ", mem.memid.c_str(), idx, module->name.c_str());
- RTLIL::SigSpec clk = RTLIL::SigSpec(RTLIL::State::Sx);
- bool clk_polarity = 0;
- candidate_dffs.clear();
-
- RTLIL::SigSpec sig_addr = cell->getPort(ID::ADDR);
- if (!find_sig_before_dff(sig_addr, clk, clk_polarity)) {
- log("no (compatible) $dff for address input found.\n");
+ FfData ff;
+ pool<std::pair<Cell *, int>> bits;
+ if (!merger.find_input_ff(port.addr, ff, bits)) {
+ log("no address FF found.\n");
return;
}
-
- RTLIL::SigSpec sig_data = cell->getPort(ID::DATA);
- if (!find_sig_before_dff(sig_data, clk, clk_polarity)) {
- log("no (compatible) $dff for data input found.\n");
+ if (!ff.has_clk) {
+ log("address latches are not supported.\n");
return;
}
-
- RTLIL::SigSpec sig_en = cell->getPort(ID::EN);
- if (!find_sig_before_dff(sig_en, clk, clk_polarity)) {
- log("no (compatible) $dff for enable input found.\n");
+ if (ff.has_aload) {
+ log("address FF has async load, not supported.\n");
return;
}
-
- if (clk != RTLIL::SigSpec(RTLIL::State::Sx))
- {
- for (auto cell : candidate_dffs)
- forward_merged_dffs.insert(cell);
-
- cell->setPort(ID::CLK, clk);
- cell->setPort(ID::ADDR, sig_addr);
- cell->setPort(ID::DATA, sig_data);
- cell->setPort(ID::EN, sig_en);
- cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(1);
- cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity);
-
- log("merged $dff to cell.\n");
+ if (ff.has_sr || ff.has_arst) {
+ log("address FF has async set and/or reset, not supported.\n");
return;
}
-
- log("no (compatible) $dff found.\n");
- }
-
- void disconnect_dff(RTLIL::SigSpec sig)
- {
- sigmap.apply(sig);
- sig.sort_and_unify();
-
- std::stringstream sstr;
- sstr << "$memory_dff_disconnected$" << (autoidx++);
-
- RTLIL::SigSpec new_sig = module->addWire(sstr.str(), sig.size());
-
- for (auto cell : module->cells())
- if (cell->type.in(ID($dff), ID($dffe))) {
- RTLIL::SigSpec new_q = cell->getPort(ID::Q);
- new_q.replace(sig, new_sig);
- cell->setPort(ID::Q, new_q);
- }
- }
-
- void handle_rd_cell(RTLIL::Cell *cell)
- {
- log("Checking cell `%s' in module `%s': ", cell->name.c_str(), module->name.c_str());
-
- bool clk_polarity = 0;
- bool en_polarity = 0;
-
- RTLIL::SigSpec clk_data = RTLIL::SigSpec(RTLIL::State::Sx);
- RTLIL::SigSpec en_data;
- RTLIL::SigSpec sig_data = cell->getPort(ID::DATA);
-
- for (auto bit : sigmap(sig_data))
- if (sigbit_users_count[bit] > 1)
- goto skip_ff_after_read_merging;
-
- if (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data))
- {
- RTLIL::SigSpec en;
- std::vector<RTLIL::SigSpec> check_q;
-
- do {
- bool enable_invert = mux_cells_a.count(sig_data) != 0;
- Cell *mux = enable_invert ? mux_cells_a.at(sig_data) : mux_cells_b.at(sig_data);
- check_q.push_back(sigmap(mux->getPort(enable_invert ? ID::B : ID::A)));
- sig_data = sigmap(mux->getPort(ID::Y));
- en.append(enable_invert ? module->LogicNot(NEW_ID, mux->getPort(ID::S)) : mux->getPort(ID::S));
- } while (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data));
-
- for (auto bit : sig_data)
- if (sigbit_users_count[bit] > 1)
- goto skip_ff_after_read_merging;
-
- if (find_sig_after_dffe(sig_data, clk_data, clk_polarity, en_data, en_polarity) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx) &&
- std::all_of(check_q.begin(), check_q.end(), [&](const SigSpec &cq) {return cq == sig_data; }))
- {
- if (en_data != State::S1 || !en_polarity) {
- if (!en_polarity)
- en_data = module->LogicNot(NEW_ID, en_data);
- en.append(en_data);
- }
- disconnect_dff(sig_data);
- cell->setPort(ID::CLK, clk_data);
- cell->setPort(ID::EN, en.size() > 1 ? module->ReduceAnd(NEW_ID, en) : en);
- cell->setPort(ID::DATA, sig_data);
- cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(1);
- cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity);
- cell->parameters[ID::TRANSPARENT] = RTLIL::Const(0);
- log("merged data $dff with rd enable to cell.\n");
- return;
- }
+ // Trick part: this transform is invalid if the initial
+ // value of the FF is fully-defined. However, we
+ // cannot simply reject FFs with any defined init bit,
+ // as this is often the result of merging a const bit.
+ if (ff.val_init.is_fully_def()) {
+ log("address FF has fully-defined init value, not supported.\n");
+ return;
}
- else
- {
- if (find_sig_after_dffe(sig_data, clk_data, clk_polarity, en_data, en_polarity) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx))
- {
- if (!en_polarity)
- en_data = module->LogicNot(NEW_ID, en_data);
- disconnect_dff(sig_data);
- cell->setPort(ID::CLK, clk_data);
- cell->setPort(ID::EN, en_data);
- cell->setPort(ID::DATA, sig_data);
- cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(1);
- cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity);
- cell->parameters[ID::TRANSPARENT] = RTLIL::Const(0);
- log("merged data $dff to cell.\n");
+ for (int i = 0; i < GetSize(mem.wr_ports); i++) {
+ auto &wport = mem.wr_ports[i];
+ if (!wport.clk_enable || wport.clk != ff.sig_clk || wport.clk_polarity != ff.pol_clk) {
+ log("address FF clock is not compatible with write clock.\n");
return;
}
}
-
- skip_ff_after_read_merging:;
- RTLIL::SigSpec clk_addr = RTLIL::SigSpec(RTLIL::State::Sx);
- RTLIL::SigSpec sig_addr = cell->getPort(ID::ADDR);
- if (find_sig_before_dff(sig_addr, clk_addr, clk_polarity) &&
- clk_addr != RTLIL::SigSpec(RTLIL::State::Sx))
- {
- cell->setPort(ID::CLK, clk_addr);
- cell->setPort(ID::EN, State::S1);
- cell->setPort(ID::ADDR, sig_addr);
- cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(1);
- cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity);
- cell->parameters[ID::TRANSPARENT] = RTLIL::Const(1);
- log("merged address $dff to cell.\n");
- return;
- }
-
- log("no (compatible) $dff found.\n");
+ // Now we're commited to merge it.
+ merger.mark_input_ff(bits);
+ // If the address FF has enable and/or sync reset, unmap it.
+ ff.unmap_ce_srst();
+ port.clk = ff.sig_clk;
+ port.en = State::S1;
+ port.addr = ff.sig_d;
+ port.clk_enable = true;
+ port.clk_polarity = ff.pol_clk;
+ for (int i = 0; i < GetSize(mem.wr_ports); i++)
+ port.transparency_mask[i] = true;
+ mem.emit();
+ log("merged address FF to cell.\n");
}
- void run(bool flag_wr_only)
+ void run()
{
- for (auto wire : module->wires()) {
- if (wire->port_output)
- for (auto bit : sigmap(wire))
- sigbit_users_count[bit]++;
- }
-
- for (auto cell : module->cells()) {
- if (cell->type.in(ID($dff), ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)))
- dff_cells.push_back(cell);
- if (cell->type == ID($mux)) {
- mux_cells_a[sigmap(cell->getPort(ID::A))] = cell;
- mux_cells_b[sigmap(cell->getPort(ID::B))] = cell;
+ std::vector<Mem> memories = Mem::get_selected_memories(module);
+ for (auto &mem : memories) {
+ QuickConeSat qcsat(modwalker);
+ for (int i = 0; i < GetSize(mem.rd_ports); i++) {
+ if (!mem.rd_ports[i].clk_enable)
+ handle_rd_port(mem, qcsat, i);
}
- if (cell->type.in(ID($not), ID($_NOT_)) || (cell->type == ID($logic_not) && GetSize(cell->getPort(ID::A)) == 1)) {
- SigSpec sig_a = cell->getPort(ID::A);
- SigSpec sig_y = cell->getPort(ID::Y);
- if (cell->type == ID($not))
- sig_a.extend_u0(GetSize(sig_y), cell->getParam(ID::A_SIGNED).as_bool());
- if (cell->type == ID($logic_not))
- sig_y.extend_u0(1);
- for (int i = 0; i < GetSize(sig_y); i++)
- invbits[sig_y[i]] = sig_a[i];
+ }
+ for (auto &mem : memories) {
+ for (int i = 0; i < GetSize(mem.rd_ports); i++) {
+ if (!mem.rd_ports[i].clk_enable)
+ handle_rd_port_addr(mem, i);
}
- for (auto &conn : cell->connections())
- if (!cell->known() || cell->input(conn.first))
- for (auto bit : sigmap(conn.second))
- sigbit_users_count[bit]++;
}
-
- for (auto cell : module->selected_cells())
- if (cell->type == ID($memwr) && !cell->parameters[ID::CLK_ENABLE].as_bool())
- handle_wr_cell(cell);
-
- if (!flag_wr_only)
- for (auto cell : module->selected_cells())
- if (cell->type == ID($memrd) && !cell->parameters[ID::CLK_ENABLE].as_bool())
- handle_rd_cell(cell);
}
};
struct MemoryDffPass : public Pass {
- MemoryDffPass() : Pass("memory_dff", "merge input/output DFFs into memories") { }
+ MemoryDffPass() : Pass("memory_dff", "merge input/output DFFs into memory read ports") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" memory_dff [options] [selection]\n");
log("\n");
- log("This pass detects DFFs at memory ports and merges them into the memory port.\n");
+ log("This pass detects DFFs at memory read ports and merges them into the memory port.\n");
log("I.e. it consumes an asynchronous memory port and the flip-flops at its\n");
log("interface and yields a synchronous memory port.\n");
log("\n");
- log(" -nordfff\n");
- log(" do not merge registers on read ports\n");
- log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
- bool flag_wr_only = false;
-
- log_header(design, "Executing MEMORY_DFF pass (merging $dff cells to $memrd and $memwr).\n");
+ log_header(design, "Executing MEMORY_DFF pass (merging $dff cells to $memrd).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
- if (args[argidx] == "-nordff" || args[argidx] == "-wr_only") {
- flag_wr_only = true;
- continue;
- }
break;
}
extra_args(args, argidx, design);
for (auto mod : design->selected_modules()) {
MemoryDffWorker worker(mod);
- worker.run(flag_wr_only);
+ worker.run();
}
}
} MemoryDffPass;
diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc
index 032b8fbbd..ca1ca483d 100644
--- a/passes/memory/memory_map.cc
+++ b/passes/memory/memory_map.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -34,10 +34,12 @@ struct MemoryMapWorker
RTLIL::Design *design;
RTLIL::Module *module;
+ SigMap sigmap;
+ FfInitVals initvals;
std::map<std::pair<RTLIL::SigSpec, RTLIL::SigSpec>, RTLIL::SigBit> decoder_cache;
- MemoryMapWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module) {}
+ MemoryMapWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module), sigmap(module), initvals(&sigmap, module) {}
std::string map_case(std::string value) const
{
@@ -151,11 +153,9 @@ struct MemoryMapWorker
continue;
}
if (!port.clk_enable) {
- if (port.addr.is_fully_const()) {
- // FIXME: Actually we should check for port.en.is_fully_const() also and
- // create a $adff cell with this ports port.en input as reset pin when port.en
- // is not a simple static 1.
- static_cells_map[port.addr.as_int() - mem.start_offset] = port.data;
+ if (port.addr.is_fully_const() && port.en.is_fully_ones()) {
+ for (int sub = 0; sub < (1 << port.wide_log2); sub++)
+ static_cells_map[port.addr.as_int() + sub] = port.data.extract(sub * mem.width, mem.width);
static_ports.insert(i);
continue;
}
@@ -176,22 +176,24 @@ struct MemoryMapWorker
log("Mapping memory %s in module %s:\n", mem.memid.c_str(), module->name.c_str());
- std::vector<RTLIL::SigSpec> data_reg_in;
- std::vector<RTLIL::SigSpec> data_reg_out;
+ int abits = ceil_log2(mem.size);
+ std::vector<RTLIL::SigSpec> data_reg_in(1 << abits);
+ std::vector<RTLIL::SigSpec> data_reg_out(1 << abits);
int count_static = 0;
for (int i = 0; i < mem.size; i++)
{
- if (static_cells_map.count(i) > 0)
+ int addr = i + mem.start_offset;
+ int idx = addr & ((1 << abits) - 1);
+ if (static_cells_map.count(addr) > 0)
{
- data_reg_in.push_back(RTLIL::SigSpec(RTLIL::State::Sz, mem.width));
- data_reg_out.push_back(static_cells_map[i]);
+ data_reg_out[idx] = static_cells_map[addr];
count_static++;
}
else
{
- RTLIL::Cell *c = module->addCell(genid(mem.memid, "", i), ID($dff));
+ RTLIL::Cell *c = module->addCell(genid(mem.memid, "", addr), ID($dff));
c->parameters[ID::WIDTH] = mem.width;
if (GetSize(refclock) != 0) {
c->parameters[ID::CLK_POLARITY] = RTLIL::Const(refclock_pol);
@@ -201,13 +203,13 @@ struct MemoryMapWorker
c->setPort(ID::CLK, RTLIL::SigSpec(RTLIL::State::S0));
}
- RTLIL::Wire *w_in = module->addWire(genid(mem.memid, "", i, "$d"), mem.width);
- data_reg_in.push_back(RTLIL::SigSpec(w_in));
- c->setPort(ID::D, data_reg_in.back());
+ RTLIL::Wire *w_in = module->addWire(genid(mem.memid, "", addr, "$d"), mem.width);
+ data_reg_in[idx] = w_in;
+ c->setPort(ID::D, w_in);
- std::string w_out_name = stringf("%s[%d]", mem.memid.c_str(), i);
+ std::string w_out_name = stringf("%s[%d]", mem.memid.c_str(), addr);
if (module->wires_.count(w_out_name) > 0)
- w_out_name = genid(mem.memid, "", i, "$q");
+ w_out_name = genid(mem.memid, "", addr, "$q");
RTLIL::Wire *w_out = module->addWire(w_out_name, mem.width);
SigSpec w_init = init_data.extract(i*mem.width, mem.width);
@@ -215,8 +217,8 @@ struct MemoryMapWorker
if (!w_init.is_fully_undef())
w_out->attributes[ID::init] = w_init.as_const();
- data_reg_out.push_back(RTLIL::SigSpec(w_out));
- c->setPort(ID::Q, data_reg_out.back());
+ data_reg_out[idx] = w_out;
+ c->setPort(ID::Q, w_out);
}
}
@@ -224,35 +226,31 @@ struct MemoryMapWorker
int count_dff = 0, count_mux = 0, count_wrmux = 0;
- int abits = ceil_log2(mem.size);
for (int i = 0; i < GetSize(mem.rd_ports); i++)
{
auto &port = mem.rd_ports[i];
- if (mem.extract_rdff(i))
+ if (mem.extract_rdff(i, &initvals))
count_dff++;
RTLIL::SigSpec rd_addr = port.addr;
rd_addr.extend_u0(abits, false);
- if (mem.start_offset)
- rd_addr = module->Sub(NEW_ID, rd_addr, SigSpec(mem.start_offset, abits));
-
std::vector<RTLIL::SigSpec> rd_signals;
rd_signals.push_back(port.data);
- for (int j = 0; j < abits; j++)
+ for (int j = 0; j < abits - port.wide_log2; j++)
{
std::vector<RTLIL::SigSpec> next_rd_signals;
for (size_t k = 0; k < rd_signals.size(); k++)
{
RTLIL::Cell *c = module->addCell(genid(mem.memid, "$rdmux", i, "", j, "", k), ID($mux));
- c->parameters[ID::WIDTH] = mem.width;
+ c->parameters[ID::WIDTH] = GetSize(port.data);
c->setPort(ID::Y, rd_signals[k]);
c->setPort(ID::S, rd_addr.extract(abits-j-1, 1));
count_mux++;
- c->setPort(ID::A, module->addWire(genid(mem.memid, "$rdmux", i, "", j, "", k, "$a"), mem.width));
- c->setPort(ID::B, module->addWire(genid(mem.memid, "$rdmux", i, "", j, "", k, "$b"), mem.width));
+ c->setPort(ID::A, module->addWire(genid(mem.memid, "$rdmux", i, "", j, "", k, "$a"), GetSize(port.data)));
+ c->setPort(ID::B, module->addWire(genid(mem.memid, "$rdmux", i, "", j, "", k, "$b"), GetSize(port.data)));
next_rd_signals.push_back(c->getPort(ID::A));
next_rd_signals.push_back(c->getPort(ID::B));
@@ -261,37 +259,38 @@ struct MemoryMapWorker
next_rd_signals.swap(rd_signals);
}
- for (int j = 0; j < mem.size; j++)
- module->connect(RTLIL::SigSig(rd_signals[j], data_reg_out[j]));
+ for (int j = 0; j < (1 << abits); j++)
+ if (data_reg_out[j] != SigSpec())
+ module->connect(RTLIL::SigSig(rd_signals[j >> port.wide_log2].extract((j & ((1 << port.wide_log2) - 1)) * mem.width, mem.width), data_reg_out[j]));
}
log(" read interface: %d $dff and %d $mux cells.\n", count_dff, count_mux);
for (int i = 0; i < mem.size; i++)
{
- if (static_cells_map.count(i) > 0)
+ int addr = i + mem.start_offset;
+ int idx = addr & ((1 << abits) - 1);
+ if (static_cells_map.count(addr) > 0)
continue;
- RTLIL::SigSpec sig = data_reg_out[i];
+ RTLIL::SigSpec sig = data_reg_out[idx];
for (int j = 0; j < GetSize(mem.wr_ports); j++)
{
auto &port = mem.wr_ports[j];
- RTLIL::SigSpec wr_addr = port.addr;
-
- if (mem.start_offset)
- wr_addr = module->Sub(NEW_ID, wr_addr, SigSpec(mem.start_offset, GetSize(wr_addr)));
+ RTLIL::SigSpec wr_addr = port.addr.extract_end(port.wide_log2);
+ RTLIL::Wire *w_seladdr = addr_decode(wr_addr, RTLIL::SigSpec(addr >> port.wide_log2, GetSize(wr_addr)));
- RTLIL::Wire *w_seladdr = addr_decode(wr_addr, RTLIL::SigSpec(i, GetSize(wr_addr)));
+ int sub = addr & ((1 << port.wide_log2) - 1);
int wr_offset = 0;
- while (wr_offset < port.en.size())
+ while (wr_offset < mem.width)
{
int wr_width = 1;
- RTLIL::SigSpec wr_bit = port.en.extract(wr_offset, 1);
+ RTLIL::SigSpec wr_bit = port.en.extract(wr_offset + sub * mem.width, 1);
- while (wr_offset + wr_width < port.en.size()) {
- RTLIL::SigSpec next_wr_bit = port.en.extract(wr_offset + wr_width, 1);
+ while (wr_offset + wr_width < mem.width) {
+ RTLIL::SigSpec next_wr_bit = port.en.extract(wr_offset + wr_width + sub * mem.width, 1);
if (next_wr_bit != wr_bit)
break;
wr_width++;
@@ -301,7 +300,7 @@ struct MemoryMapWorker
if (wr_bit != State::S1)
{
- RTLIL::Cell *c = module->addCell(genid(mem.memid, "$wren", i, "", j, "", wr_offset), ID($and));
+ RTLIL::Cell *c = module->addCell(genid(mem.memid, "$wren", addr, "", j, "", wr_offset), ID($and));
c->parameters[ID::A_SIGNED] = RTLIL::Const(0);
c->parameters[ID::B_SIGNED] = RTLIL::Const(0);
c->parameters[ID::A_WIDTH] = RTLIL::Const(1);
@@ -310,17 +309,17 @@ struct MemoryMapWorker
c->setPort(ID::A, w);
c->setPort(ID::B, wr_bit);
- w = module->addWire(genid(mem.memid, "$wren", i, "", j, "", wr_offset, "$y"));
+ w = module->addWire(genid(mem.memid, "$wren", addr, "", j, "", wr_offset, "$y"));
c->setPort(ID::Y, RTLIL::SigSpec(w));
}
- RTLIL::Cell *c = module->addCell(genid(mem.memid, "$wrmux", i, "", j, "", wr_offset), ID($mux));
+ RTLIL::Cell *c = module->addCell(genid(mem.memid, "$wrmux", addr, "", j, "", wr_offset), ID($mux));
c->parameters[ID::WIDTH] = wr_width;
c->setPort(ID::A, sig.extract(wr_offset, wr_width));
- c->setPort(ID::B, port.data.extract(wr_offset, wr_width));
+ c->setPort(ID::B, port.data.extract(wr_offset + sub * mem.width, wr_width));
c->setPort(ID::S, RTLIL::SigSpec(w));
- w = module->addWire(genid(mem.memid, "$wrmux", i, "", j, "", wr_offset, "$y"), wr_width);
+ w = module->addWire(genid(mem.memid, "$wrmux", addr, "", j, "", wr_offset, "$y"), wr_width);
c->setPort(ID::Y, w);
sig.replace(wr_offset, w);
@@ -329,7 +328,7 @@ struct MemoryMapWorker
}
}
- module->connect(RTLIL::SigSig(data_reg_in[i], sig));
+ module->connect(RTLIL::SigSig(data_reg_in[idx], sig));
}
log(" write interface: %d write mux blocks.\n", count_wrmux);
diff --git a/passes/memory/memory_memx.cc b/passes/memory/memory_memx.cc
index 02e00cf30..7edc26caa 100644
--- a/passes/memory/memory_memx.cc
+++ b/passes/memory/memory_memx.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -17,11 +17,8 @@
*
*/
-#include "kernel/register.h"
-#include "kernel/log.h"
-#include <sstream>
-#include <set>
-#include <stdlib.h>
+#include "kernel/yosys.h"
+#include "kernel/mem.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -38,53 +35,45 @@ struct MemoryMemxPass : public Pass {
log("behavior for out-of-bounds memory reads and writes.\n");
log("\n");
}
+
+ SigSpec make_addr_check(Mem &mem, SigSpec addr) {
+ int start_addr = mem.start_offset;
+ int end_addr = mem.start_offset + mem.size;
+
+ addr.extend_u0(32);
+
+ SigSpec res = mem.module->Nex(NEW_ID, mem.module->ReduceXor(NEW_ID, addr), mem.module->ReduceXor(NEW_ID, {addr, State::S1}));
+ if (start_addr != 0)
+ res = mem.module->LogicAnd(NEW_ID, res, mem.module->Ge(NEW_ID, addr, start_addr));
+ res = mem.module->LogicAnd(NEW_ID, res, mem.module->Lt(NEW_ID, addr, end_addr));
+ return res;
+ }
+
void execute(std::vector<std::string> args, RTLIL::Design *design) override {
log_header(design, "Executing MEMORY_MEMX pass (converting $mem cells to logic and flip-flops).\n");
extra_args(args, 1, design);
for (auto module : design->selected_modules())
+ for (auto &mem : Mem::get_selected_memories(module))
{
- vector<Cell*> mem_port_cells;
-
- for (auto cell : module->selected_cells())
- if (cell->type.in(ID($memrd), ID($memwr)))
- mem_port_cells.push_back(cell);
-
- for (auto cell : mem_port_cells)
+ for (auto &port : mem.rd_ports)
{
- IdString memid = cell->getParam(ID::MEMID).decode_string();
- RTLIL::Memory *mem = module->memories.at(memid);
+ if (port.clk_enable)
+ log_error("Memory %s.%s has a synchronous read port. Synchronous read ports are not supported by memory_memx!\n",
+ log_id(module), log_id(mem.memid));
- int lowest_addr = mem->start_offset;
- int highest_addr = mem->start_offset + mem->size - 1;
-
- SigSpec addr = cell->getPort(ID::ADDR);
- addr.extend_u0(32);
-
- SigSpec addr_ok = module->Nex(NEW_ID, module->ReduceXor(NEW_ID, addr), module->ReduceXor(NEW_ID, {addr, State::S1}));
- if (lowest_addr != 0)
- addr_ok = module->LogicAnd(NEW_ID, addr_ok, module->Ge(NEW_ID, addr, lowest_addr));
- addr_ok = module->LogicAnd(NEW_ID, addr_ok, module->Le(NEW_ID, addr, highest_addr));
-
- if (cell->type == ID($memrd))
- {
- if (cell->getParam(ID::CLK_ENABLE).as_bool())
- log_error("Cell %s.%s (%s) has an enabled clock. Clocked $memrd cells are not supported by memory_memx!\n",
- log_id(module), log_id(cell), log_id(cell->type));
-
- SigSpec rdata = cell->getPort(ID::DATA);
- Wire *raw_rdata = module->addWire(NEW_ID, GetSize(rdata));
- module->addMux(NEW_ID, SigSpec(State::Sx, GetSize(rdata)), raw_rdata, addr_ok, rdata);
- cell->setPort(ID::DATA, raw_rdata);
- }
+ SigSpec addr_ok = make_addr_check(mem, port.addr);
+ Wire *raw_rdata = module->addWire(NEW_ID, GetSize(port.data));
+ module->addMux(NEW_ID, SigSpec(State::Sx, GetSize(port.data)), raw_rdata, addr_ok, port.data);
+ port.data = raw_rdata;
+ }
- if (cell->type == ID($memwr))
- {
- SigSpec en = cell->getPort(ID::EN);
- en = module->And(NEW_ID, en, addr_ok.repeat(GetSize(en)));
- cell->setPort(ID::EN, en);
- }
+ for (auto &port : mem.wr_ports) {
+ SigSpec addr_ok = make_addr_check(mem, port.addr);
+ port.en = module->And(NEW_ID, port.en, addr_ok.repeat(GetSize(port.en)));
}
+
+ mem.emit();
}
}
} MemoryMemxPass;
diff --git a/passes/memory/memory_narrow.cc b/passes/memory/memory_narrow.cc
new file mode 100644
index 000000000..cf5e43465
--- /dev/null
+++ b/passes/memory/memory_narrow.cc
@@ -0,0 +1,67 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2020 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * 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/mem.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct MemoryNarrowPass : public Pass {
+ MemoryNarrowPass() : Pass("memory_narrow", "split up wide memory ports") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" memory_narrow [options] [selection]\n");
+ log("\n");
+ log("This pass splits up wide memory ports into several narrow ports.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing MEMORY_NARROW pass (splitting up wide memory ports).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules()) {
+ for (auto &mem : Mem::get_selected_memories(module))
+ {
+ bool wide = false;
+ for (auto &port : mem.rd_ports)
+ if (port.wide_log2)
+ wide = true;
+ for (auto &port : mem.wr_ports)
+ if (port.wide_log2)
+ wide = true;
+ if (wide) {
+ mem.narrow();
+ mem.emit();
+ }
+ }
+ }
+ }
+} MemoryNarrowPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/memory/memory_nordff.cc b/passes/memory/memory_nordff.cc
index a4fdcfc38..3253c8f60 100644
--- a/passes/memory/memory_nordff.cc
+++ b/passes/memory/memory_nordff.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -33,7 +33,7 @@ struct MemoryNordffPass : public Pass {
log(" memory_nordff [options] [selection]\n");
log("\n");
log("This pass extracts FFs from memory read ports. This results in a netlist\n");
- log("similar to what one would get from calling memory_dff with -nordff.\n");
+ log("similar to what one would get from not calling memory_dff.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -51,15 +51,22 @@ struct MemoryNordffPass : public Pass {
extra_args(args, argidx, design);
for (auto module : design->selected_modules())
- for (auto &mem : Mem::get_selected_memories(module))
{
- bool changed = false;
- for (int i = 0; i < GetSize(mem.rd_ports); i++)
- if (mem.extract_rdff(i))
- changed = true;
+ SigMap sigmap(module);
+ FfInitVals initvals(&sigmap, module);
+ for (auto &mem : Mem::get_selected_memories(module))
+ {
+ bool changed = false;
+ for (int i = 0; i < GetSize(mem.rd_ports); i++) {
+ if (mem.rd_ports[i].clk_enable) {
+ mem.extract_rdff(i, &initvals);
+ changed = true;
+ }
+ }
- if (changed)
- mem.emit();
+ if (changed)
+ mem.emit();
+ }
}
}
} MemoryNordffPass;
diff --git a/passes/memory/memory_share.cc b/passes/memory/memory_share.cc
index 7315aeae1..ceea725d8 100644
--- a/passes/memory/memory_share.cc
+++ b/passes/memory/memory_share.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -18,467 +18,260 @@
*/
#include "kernel/yosys.h"
-#include "kernel/satgen.h"
+#include "kernel/qcsat.h"
#include "kernel/sigtools.h"
#include "kernel/modtools.h"
+#include "kernel/mem.h"
+#include "kernel/ffinit.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-bool memcells_cmp(RTLIL::Cell *a, RTLIL::Cell *b)
-{
- if (a->type == ID($memrd) && b->type == ID($memrd))
- return a->name < b->name;
- if (a->type == ID($memrd) || b->type == ID($memrd))
- return (a->type == ID($memrd)) < (b->type == ID($memrd));
- return a->parameters.at(ID::PRIORITY).as_int() < b->parameters.at(ID::PRIORITY).as_int();
-}
-
struct MemoryShareWorker
{
RTLIL::Design *design;
RTLIL::Module *module;
SigMap sigmap, sigmap_xmux;
ModWalker modwalker;
- CellTypes cone_ct;
-
- std::map<RTLIL::SigBit, std::pair<RTLIL::Cell*, int>> sig_to_mux;
- std::map<pair<std::set<std::map<SigBit, bool>>, SigBit>, SigBit> conditions_logic_cache;
-
-
- // -----------------------------------------------------------------
- // Converting feedbacks to async read ports to proper enable signals
- // -----------------------------------------------------------------
-
- bool find_data_feedback(const std::set<RTLIL::SigBit> &async_rd_bits, RTLIL::SigBit sig,
- std::map<RTLIL::SigBit, bool> &state, std::set<std::map<RTLIL::SigBit, bool>> &conditions)
- {
- if (async_rd_bits.count(sig)) {
- conditions.insert(state);
- return true;
- }
-
- if (sig_to_mux.count(sig) == 0)
- return false;
-
- RTLIL::Cell *cell = sig_to_mux.at(sig).first;
- int bit_idx = sig_to_mux.at(sig).second;
-
- std::vector<RTLIL::SigBit> sig_a = sigmap(cell->getPort(ID::A));
- std::vector<RTLIL::SigBit> sig_b = sigmap(cell->getPort(ID::B));
- std::vector<RTLIL::SigBit> sig_s = sigmap(cell->getPort(ID::S));
- std::vector<RTLIL::SigBit> sig_y = sigmap(cell->getPort(ID::Y));
- log_assert(sig_y.at(bit_idx) == sig);
-
- for (int i = 0; i < int(sig_s.size()); i++)
- if (state.count(sig_s[i]) && state.at(sig_s[i]) == true) {
- if (find_data_feedback(async_rd_bits, sig_b.at(bit_idx + i*sig_y.size()), state, conditions)) {
- RTLIL::SigSpec new_b = cell->getPort(ID::B);
- new_b.replace(bit_idx + i*sig_y.size(), RTLIL::State::Sx);
- cell->setPort(ID::B, new_b);
- }
+ FfInitVals initvals;
+ bool flag_widen;
+ bool flag_sat;
+
+ // --------------------------------------------------
+ // Consolidate read ports that read the same address
+ // (or close enough to be merged to wide ports)
+ // --------------------------------------------------
+
+ // A simple function to detect ports that couldn't possibly collide
+ // because of opposite const address bits (simplistic, but enough
+ // to fix problems with inferring wide ports).
+ bool rdwr_can_collide(Mem &mem, int ridx, int widx) {
+ auto &rport = mem.rd_ports[ridx];
+ auto &wport = mem.wr_ports[widx];
+ for (int i = std::max(rport.wide_log2, wport.wide_log2); i < GetSize(rport.addr) && i < GetSize(wport.addr); i++) {
+ if (rport.addr[i] == State::S1 && wport.addr[i] == State::S0)
+ return false;
+ if (rport.addr[i] == State::S0 && wport.addr[i] == State::S1)
return false;
- }
-
-
- for (int i = 0; i < int(sig_s.size()); i++)
- {
- if (state.count(sig_s[i]) && state.at(sig_s[i]) == false)
- continue;
-
- std::map<RTLIL::SigBit, bool> new_state = state;
- new_state[sig_s[i]] = true;
-
- if (find_data_feedback(async_rd_bits, sig_b.at(bit_idx + i*sig_y.size()), new_state, conditions)) {
- RTLIL::SigSpec new_b = cell->getPort(ID::B);
- new_b.replace(bit_idx + i*sig_y.size(), RTLIL::State::Sx);
- cell->setPort(ID::B, new_b);
- }
- }
-
- std::map<RTLIL::SigBit, bool> new_state = state;
- for (int i = 0; i < int(sig_s.size()); i++)
- new_state[sig_s[i]] = false;
-
- if (find_data_feedback(async_rd_bits, sig_a.at(bit_idx), new_state, conditions)) {
- RTLIL::SigSpec new_a = cell->getPort(ID::A);
- new_a.replace(bit_idx, RTLIL::State::Sx);
- cell->setPort(ID::A, new_a);
}
-
- return false;
+ return true;
}
- RTLIL::SigBit conditions_to_logic(std::set<std::map<RTLIL::SigBit, bool>> &conditions, SigBit olden, int &created_conditions)
- {
- auto key = make_pair(conditions, olden);
-
- if (conditions_logic_cache.count(key))
- return conditions_logic_cache.at(key);
-
- RTLIL::SigSpec terms;
- for (auto &cond : conditions) {
- RTLIL::SigSpec sig1, sig2;
- for (auto &it : cond) {
- sig1.append(it.first);
- sig2.append(it.second ? RTLIL::State::S1 : RTLIL::State::S0);
- }
- terms.append(module->Ne(NEW_ID, sig1, sig2));
- created_conditions++;
+ bool merge_rst_value(Mem &mem, Const &res, int wide_log2, const Const &src1, int sub1, const Const &src2, int sub2) {
+ res = Const(State::Sx, mem.width << wide_log2);
+ for (int i = 0; i < GetSize(src1); i++)
+ res[i + sub1 * mem.width] = src1[i];
+ for (int i = 0; i < GetSize(src2); i++) {
+ if (src2[i] == State::Sx)
+ continue;
+ auto &dst = res[i + sub2 * mem.width];
+ if (dst == src2[i])
+ continue;
+ if (dst != State::Sx)
+ return false;
+ dst = src2[i];
}
-
- if (olden.wire != nullptr || olden != State::S1)
- terms.append(olden);
-
- if (GetSize(terms) == 0)
- terms = State::S1;
-
- if (GetSize(terms) > 1)
- terms = module->ReduceAnd(NEW_ID, terms);
-
- return conditions_logic_cache[key] = terms;
+ return true;
}
- void translate_rd_feedback_to_en(std::string memid, std::vector<RTLIL::Cell*> &rd_ports, std::vector<RTLIL::Cell*> &wr_ports)
+ bool consolidate_rd_by_addr(Mem &mem)
{
- std::map<RTLIL::SigSpec, std::vector<std::set<RTLIL::SigBit>>> async_rd_bits;
- std::map<RTLIL::SigBit, std::set<RTLIL::SigBit>> muxtree_upstream_map;
- std::set<RTLIL::SigBit> non_feedback_nets;
-
- for (auto wire : module->wires())
- if (wire->port_output) {
- std::vector<RTLIL::SigBit> bits = sigmap(wire);
- non_feedback_nets.insert(bits.begin(), bits.end());
- }
-
- for (auto cell : module->cells())
- {
- bool ignore_data_port = false;
-
- if (cell->type.in(ID($mux), ID($pmux)))
- {
- std::vector<RTLIL::SigBit> sig_a = sigmap(cell->getPort(ID::A));
- std::vector<RTLIL::SigBit> sig_b = sigmap(cell->getPort(ID::B));
- std::vector<RTLIL::SigBit> sig_s = sigmap(cell->getPort(ID::S));
- std::vector<RTLIL::SigBit> sig_y = sigmap(cell->getPort(ID::Y));
-
- non_feedback_nets.insert(sig_s.begin(), sig_s.end());
+ if (GetSize(mem.rd_ports) <= 1)
+ return false;
- for (int i = 0; i < int(sig_y.size()); i++) {
- muxtree_upstream_map[sig_y[i]].insert(sig_a[i]);
- for (int j = 0; j < int(sig_s.size()); j++)
- muxtree_upstream_map[sig_y[i]].insert(sig_b[i + j*sig_y.size()]);
- }
+ log("Consolidating read ports of memory %s.%s by address:\n", log_id(module), log_id(mem.memid));
+ bool changed = false;
+ for (int i = 0; i < GetSize(mem.rd_ports); i++)
+ {
+ auto &port1 = mem.rd_ports[i];
+ if (port1.removed)
continue;
- }
-
- if (cell->type.in(ID($memwr), ID($memrd)) &&
- cell->parameters.at(ID::MEMID).decode_string() == memid)
- ignore_data_port = true;
-
- for (auto conn : cell->connections())
+ for (int j = i + 1; j < GetSize(mem.rd_ports); j++)
{
- if (ignore_data_port && conn.first == ID::DATA)
+ auto &port2 = mem.rd_ports[j];
+ if (port2.removed)
continue;
- std::vector<RTLIL::SigBit> bits = sigmap(conn.second);
- non_feedback_nets.insert(bits.begin(), bits.end());
- }
- }
-
- std::set<RTLIL::SigBit> expand_non_feedback_nets = non_feedback_nets;
- while (!expand_non_feedback_nets.empty())
- {
- std::set<RTLIL::SigBit> new_expand_non_feedback_nets;
-
- for (auto &bit : expand_non_feedback_nets)
- if (muxtree_upstream_map.count(bit))
- for (auto &new_bit : muxtree_upstream_map.at(bit))
- if (!non_feedback_nets.count(new_bit)) {
- non_feedback_nets.insert(new_bit);
- new_expand_non_feedback_nets.insert(new_bit);
- }
-
- expand_non_feedback_nets.swap(new_expand_non_feedback_nets);
- }
-
- for (auto cell : rd_ports)
- {
- if (cell->parameters.at(ID::CLK_ENABLE).as_bool())
- continue;
-
- RTLIL::SigSpec sig_addr = sigmap(cell->getPort(ID::ADDR));
- std::vector<RTLIL::SigBit> sig_data = sigmap(cell->getPort(ID::DATA));
-
- for (int i = 0; i < int(sig_data.size()); i++)
- if (non_feedback_nets.count(sig_data[i]))
- goto not_pure_feedback_port;
-
- async_rd_bits[sig_addr].resize(max(async_rd_bits.size(), sig_data.size()));
- for (int i = 0; i < int(sig_data.size()); i++)
- async_rd_bits[sig_addr][i].insert(sig_data[i]);
-
- not_pure_feedback_port:;
- }
-
- if (async_rd_bits.empty())
- return;
-
- log("Populating enable bits on write ports of memory %s.%s with aync read feedback:\n", log_id(module), log_id(memid));
-
- for (auto cell : wr_ports)
- {
- RTLIL::SigSpec sig_addr = sigmap_xmux(cell->getPort(ID::ADDR));
- if (!async_rd_bits.count(sig_addr))
- continue;
-
- log(" Analyzing write port %s.\n", log_id(cell));
-
- std::vector<RTLIL::SigBit> cell_data = cell->getPort(ID::DATA);
- std::vector<RTLIL::SigBit> cell_en = cell->getPort(ID::EN);
-
- int created_conditions = 0;
- for (int i = 0; i < int(cell_data.size()); i++)
- if (cell_en[i] != RTLIL::SigBit(RTLIL::State::S0))
+ if (port1.clk_enable != port2.clk_enable)
+ continue;
+ if (port1.clk_enable) {
+ if (port1.clk != port2.clk)
+ continue;
+ if (port1.clk_polarity != port2.clk_polarity)
+ continue;
+ }
+ if (port1.en != port2.en)
+ continue;
+ if (port1.arst != port2.arst)
+ continue;
+ if (port1.srst != port2.srst)
+ continue;
+ if (port1.ce_over_srst != port2.ce_over_srst)
+ continue;
+ // If the width of the ports doesn't match, they can still be
+ // merged by widening the narrow one. Check if the conditions
+ // hold for that.
+ int wide_log2 = std::max(port1.wide_log2, port2.wide_log2);
+ SigSpec addr1 = sigmap_xmux(port1.addr);
+ SigSpec addr2 = sigmap_xmux(port2.addr);
+ if (GetSize(addr1) <= wide_log2)
+ continue;
+ if (GetSize(addr2) <= wide_log2)
+ continue;
+ if (!addr1.extract(0, wide_log2).is_fully_const())
+ continue;
+ if (!addr2.extract(0, wide_log2).is_fully_const())
+ continue;
+ if (addr1.extract_end(wide_log2) != addr2.extract_end(wide_log2)) {
+ // Incompatible addresses after widening. Last chance — widen both
+ // ports by one more bit to merge them.
+ if (!flag_widen)
+ continue;
+ wide_log2++;
+ if (addr1.extract_end(wide_log2) != addr2.extract_end(wide_log2))
+ continue;
+ if (!addr1.extract(0, wide_log2).is_fully_const())
+ continue;
+ if (!addr2.extract(0, wide_log2).is_fully_const())
+ continue;
+ }
+ // Combine init/reset values.
+ SigSpec sub1_c = port1.addr.extract(0, wide_log2);
+ log_assert(sub1_c.is_fully_const());
+ int sub1 = sub1_c.as_int();
+ SigSpec sub2_c = port2.addr.extract(0, wide_log2);
+ log_assert(sub2_c.is_fully_const());
+ int sub2 = sub2_c.as_int();
+ Const init_value, arst_value, srst_value;
+ if (!merge_rst_value(mem, init_value, wide_log2, port1.init_value, sub1, port2.init_value, sub2))
+ continue;
+ if (!merge_rst_value(mem, arst_value, wide_log2, port1.arst_value, sub1, port2.arst_value, sub2))
+ continue;
+ if (!merge_rst_value(mem, srst_value, wide_log2, port1.srst_value, sub1, port2.srst_value, sub2))
+ continue;
+ // At this point we are committed to the merge.
{
- std::map<RTLIL::SigBit, bool> state;
- std::set<std::map<RTLIL::SigBit, bool>> conditions;
-
- find_data_feedback(async_rd_bits.at(sig_addr).at(i), cell_data[i], state, conditions);
- cell_en[i] = conditions_to_logic(conditions, cell_en[i], created_conditions);
+ log(" Merging ports %d, %d (address %s).\n", i, j, log_signal(port1.addr));
+ port1.addr = addr1;
+ port2.addr = addr2;
+ mem.prepare_rd_merge(i, j, &initvals);
+ mem.widen_prep(wide_log2);
+ SigSpec new_data = module->addWire(NEW_ID, mem.width << wide_log2);
+ module->connect(port1.data, new_data.extract(sub1 * mem.width, mem.width << port1.wide_log2));
+ module->connect(port2.data, new_data.extract(sub2 * mem.width, mem.width << port2.wide_log2));
+ for (int k = 0; k < wide_log2; k++)
+ port1.addr[k] = State::S0;
+ port1.init_value = init_value;
+ port1.arst_value = arst_value;
+ port1.srst_value = srst_value;
+ port1.wide_log2 = wide_log2;
+ port1.data = new_data;
+ port2.removed = true;
+ changed = true;
}
-
- if (created_conditions) {
- log(" Added enable logic for %d different cases.\n", created_conditions);
- cell->setPort(ID::EN, cell_en);
}
}
+
+ if (changed)
+ mem.emit();
+
+ return changed;
}
// ------------------------------------------------------
// Consolidate write ports that write to the same address
+ // (or close enough to be merged to wide ports)
// ------------------------------------------------------
- RTLIL::SigSpec mask_en_naive(RTLIL::SigSpec do_mask, RTLIL::SigSpec bits, RTLIL::SigSpec mask_bits)
+ bool consolidate_wr_by_addr(Mem &mem)
{
- // this is the naive version of the function that does not care about grouping the EN bits.
-
- RTLIL::SigSpec inv_mask_bits = module->Not(NEW_ID, mask_bits);
- RTLIL::SigSpec inv_mask_bits_filtered = module->Mux(NEW_ID, RTLIL::SigSpec(RTLIL::State::S1, bits.size()), inv_mask_bits, do_mask);
- RTLIL::SigSpec result = module->And(NEW_ID, inv_mask_bits_filtered, bits);
- return result;
- }
-
- RTLIL::SigSpec mask_en_grouped(RTLIL::SigSpec do_mask, RTLIL::SigSpec bits, RTLIL::SigSpec mask_bits)
- {
- // this version of the function preserves the bit grouping in the EN bits.
-
- std::vector<RTLIL::SigBit> v_bits = bits;
- std::vector<RTLIL::SigBit> v_mask_bits = mask_bits;
-
- std::map<std::pair<RTLIL::SigBit, RTLIL::SigBit>, std::pair<int, std::vector<int>>> groups;
- RTLIL::SigSpec grouped_bits, grouped_mask_bits;
-
- for (int i = 0; i < bits.size(); i++) {
- std::pair<RTLIL::SigBit, RTLIL::SigBit> key(v_bits[i], v_mask_bits[i]);
- if (groups.count(key) == 0) {
- groups[key].first = grouped_bits.size();
- grouped_bits.append(v_bits[i]);
- grouped_mask_bits.append(v_mask_bits[i]);
- }
- groups[key].second.push_back(i);
- }
-
- std::vector<RTLIL::SigBit> grouped_result = mask_en_naive(do_mask, grouped_bits, grouped_mask_bits);
- RTLIL::SigSpec result;
-
- for (int i = 0; i < bits.size(); i++) {
- std::pair<RTLIL::SigBit, RTLIL::SigBit> key(v_bits[i], v_mask_bits[i]);
- result.append(grouped_result.at(groups.at(key).first));
- }
-
- return result;
- }
-
- void merge_en_data(RTLIL::SigSpec &merged_en, RTLIL::SigSpec &merged_data, RTLIL::SigSpec next_en, RTLIL::SigSpec next_data)
- {
- std::vector<RTLIL::SigBit> v_old_en = merged_en;
- std::vector<RTLIL::SigBit> v_next_en = next_en;
-
- // The new merged_en signal is just the old merged_en signal and next_en OR'ed together.
- // But of course we need to preserve the bit grouping..
-
- std::map<std::pair<RTLIL::SigBit, RTLIL::SigBit>, int> groups;
- std::vector<RTLIL::SigBit> grouped_old_en, grouped_next_en;
- RTLIL::SigSpec new_merged_en;
-
- for (int i = 0; i < int(v_old_en.size()); i++) {
- std::pair<RTLIL::SigBit, RTLIL::SigBit> key(v_old_en[i], v_next_en[i]);
- if (groups.count(key) == 0) {
- groups[key] = grouped_old_en.size();
- grouped_old_en.push_back(key.first);
- grouped_next_en.push_back(key.second);
- }
- }
-
- std::vector<RTLIL::SigBit> grouped_new_en = module->Or(NEW_ID, grouped_old_en, grouped_next_en);
-
- for (int i = 0; i < int(v_old_en.size()); i++) {
- std::pair<RTLIL::SigBit, RTLIL::SigBit> key(v_old_en[i], v_next_en[i]);
- new_merged_en.append(grouped_new_en.at(groups.at(key)));
- }
-
- // Create the new merged_data signal.
-
- RTLIL::SigSpec new_merged_data(RTLIL::State::Sx, merged_data.size());
-
- RTLIL::SigSpec old_data_set = module->And(NEW_ID, merged_en, merged_data);
- RTLIL::SigSpec old_data_unset = module->And(NEW_ID, merged_en, module->Not(NEW_ID, merged_data));
-
- RTLIL::SigSpec new_data_set = module->And(NEW_ID, next_en, next_data);
- RTLIL::SigSpec new_data_unset = module->And(NEW_ID, next_en, module->Not(NEW_ID, next_data));
-
- new_merged_data = module->Or(NEW_ID, new_merged_data, old_data_set);
- new_merged_data = module->And(NEW_ID, new_merged_data, module->Not(NEW_ID, old_data_unset));
-
- new_merged_data = module->Or(NEW_ID, new_merged_data, new_data_set);
- new_merged_data = module->And(NEW_ID, new_merged_data, module->Not(NEW_ID, new_data_unset));
-
- // Update merged_* signals
-
- merged_en = new_merged_en;
- merged_data = new_merged_data;
- }
-
- void consolidate_wr_by_addr(std::string memid, std::vector<RTLIL::Cell*> &wr_ports)
- {
- if (wr_ports.size() <= 1)
- return;
-
- log("Consolidating write ports of memory %s.%s by address:\n", log_id(module), log_id(memid));
-
- std::map<RTLIL::SigSpec, int> last_port_by_addr;
- std::vector<std::vector<bool>> active_bits_on_port;
+ if (GetSize(mem.wr_ports) <= 1)
+ return false;
- bool cache_clk_enable = false;
- bool cache_clk_polarity = false;
- RTLIL::SigSpec cache_clk;
+ log("Consolidating write ports of memory %s.%s by address:\n", log_id(module), log_id(mem.memid));
- for (int i = 0; i < int(wr_ports.size()); i++)
+ bool changed = false;
+ for (int i = 0; i < GetSize(mem.wr_ports); i++)
{
- RTLIL::Cell *cell = wr_ports.at(i);
- RTLIL::SigSpec addr = sigmap_xmux(cell->getPort(ID::ADDR));
-
- if (cell->parameters.at(ID::CLK_ENABLE).as_bool() != cache_clk_enable ||
- (cache_clk_enable && (sigmap(cell->getPort(ID::CLK)) != cache_clk ||
- cell->parameters.at(ID::CLK_POLARITY).as_bool() != cache_clk_polarity)))
- {
- cache_clk_enable = cell->parameters.at(ID::CLK_ENABLE).as_bool();
- cache_clk_polarity = cell->parameters.at(ID::CLK_POLARITY).as_bool();
- cache_clk = sigmap(cell->getPort(ID::CLK));
- last_port_by_addr.clear();
-
- if (cache_clk_enable)
- log(" New clock domain: %s %s\n", cache_clk_polarity ? "posedge" : "negedge", log_signal(cache_clk));
- else
- log(" New clock domain: unclocked\n");
- }
-
- log(" Port %d (%s) has addr %s.\n", i, log_id(cell), log_signal(addr));
-
- log(" Active bits: ");
- std::vector<RTLIL::SigBit> en_bits = sigmap(cell->getPort(ID::EN));
- active_bits_on_port.push_back(std::vector<bool>(en_bits.size()));
- for (int k = int(en_bits.size())-1; k >= 0; k--) {
- active_bits_on_port[i][k] = en_bits[k].wire != NULL || en_bits[k].data != RTLIL::State::S0;
- log("%c", active_bits_on_port[i][k] ? '1' : '0');
- }
- log("\n");
-
- if (last_port_by_addr.count(addr))
+ auto &port1 = mem.wr_ports[i];
+ if (port1.removed)
+ continue;
+ if (!port1.clk_enable)
+ continue;
+ for (int j = i + 1; j < GetSize(mem.wr_ports); j++)
{
- int last_i = last_port_by_addr.at(addr);
- log(" Merging port %d into this one.\n", last_i);
-
- bool found_overlapping_bits = false;
- for (int k = 0; k < int(en_bits.size()); k++) {
- if (active_bits_on_port[i][k] && active_bits_on_port[last_i][k])
- found_overlapping_bits = true;
- active_bits_on_port[i][k] = active_bits_on_port[i][k] || active_bits_on_port[last_i][k];
- }
-
- // Force this ports addr input to addr directly (skip don't care muxes)
-
- cell->setPort(ID::ADDR, addr);
-
- // If any of the ports between `last_i' and `i' write to the same address, this
- // will have priority over whatever `last_i` wrote. So we need to revisit those
- // ports and mask the EN bits accordingly.
-
- RTLIL::SigSpec merged_en = sigmap(wr_ports[last_i]->getPort(ID::EN));
-
- for (int j = last_i+1; j < i; j++)
- {
- if (wr_ports[j] == NULL)
+ auto &port2 = mem.wr_ports[j];
+ if (port2.removed)
+ continue;
+ if (!port2.clk_enable)
+ continue;
+ if (port1.clk != port2.clk)
+ continue;
+ if (port1.clk_polarity != port2.clk_polarity)
+ continue;
+ // If the width of the ports doesn't match, they can still be
+ // merged by widening the narrow one. Check if the conditions
+ // hold for that.
+ int wide_log2 = std::max(port1.wide_log2, port2.wide_log2);
+ SigSpec addr1 = sigmap_xmux(port1.addr);
+ SigSpec addr2 = sigmap_xmux(port2.addr);
+ if (GetSize(addr1) <= wide_log2)
+ continue;
+ if (GetSize(addr2) <= wide_log2)
+ continue;
+ if (!addr1.extract(0, wide_log2).is_fully_const())
+ continue;
+ if (!addr2.extract(0, wide_log2).is_fully_const())
+ continue;
+ if (addr1.extract_end(wide_log2) != addr2.extract_end(wide_log2)) {
+ // Incompatible addresses after widening. Last chance — widen both
+ // ports by one more bit to merge them.
+ if (!flag_widen)
+ continue;
+ wide_log2++;
+ if (addr1.extract_end(wide_log2) != addr2.extract_end(wide_log2))
+ continue;
+ if (!addr1.extract(0, wide_log2).is_fully_const())
+ continue;
+ if (!addr2.extract(0, wide_log2).is_fully_const())
continue;
-
- for (int k = 0; k < int(en_bits.size()); k++)
- if (active_bits_on_port[i][k] && active_bits_on_port[j][k])
- goto found_overlapping_bits_i_j;
-
- if (0) {
- found_overlapping_bits_i_j:
- log(" Creating collosion-detect logic for port %d.\n", j);
- RTLIL::SigSpec is_same_addr = module->addWire(NEW_ID);
- module->addEq(NEW_ID, addr, wr_ports[j]->getPort(ID::ADDR), is_same_addr);
- merged_en = mask_en_grouped(is_same_addr, merged_en, sigmap(wr_ports[j]->getPort(ID::EN)));
- }
}
-
- // Then we need to merge the (masked) EN and the DATA signals.
-
- RTLIL::SigSpec merged_data = wr_ports[last_i]->getPort(ID::DATA);
- if (found_overlapping_bits) {
- log(" Creating logic for merging DATA and EN ports.\n");
- merge_en_data(merged_en, merged_data, sigmap(cell->getPort(ID::EN)), sigmap(cell->getPort(ID::DATA)));
- } else {
- RTLIL::SigSpec cell_en = sigmap(cell->getPort(ID::EN));
- RTLIL::SigSpec cell_data = sigmap(cell->getPort(ID::DATA));
- for (int k = 0; k < int(en_bits.size()); k++)
- if (!active_bits_on_port[last_i][k]) {
- merged_en.replace(k, cell_en.extract(k, 1));
- merged_data.replace(k, cell_data.extract(k, 1));
- }
+ log(" Merging ports %d, %d (address %s).\n", i, j, log_signal(addr1));
+ port1.addr = addr1;
+ port2.addr = addr2;
+ mem.prepare_wr_merge(i, j, &initvals);
+ mem.widen_wr_port(i, wide_log2);
+ mem.widen_wr_port(j, wide_log2);
+ int pos = 0;
+ while (pos < GetSize(port1.data)) {
+ int epos = pos;
+ while (epos < GetSize(port1.data) && port1.en[epos] == port1.en[pos] && port2.en[epos] == port2.en[pos])
+ epos++;
+ int width = epos - pos;
+ SigBit new_en;
+ if (port2.en[pos] == State::S0) {
+ new_en = port1.en[pos];
+ } else if (port1.en[pos] == State::S0) {
+ port1.data.replace(pos, port2.data.extract(pos, width));
+ new_en = port2.en[pos];
+ } else {
+ port1.data.replace(pos, module->Mux(NEW_ID, port1.data.extract(pos, width), port2.data.extract(pos, width), port2.en[pos]));
+ new_en = module->Or(NEW_ID, port1.en[pos], port2.en[pos]);
+ }
+ for (int k = pos; k < epos; k++)
+ port1.en[k] = new_en;
+ pos = epos;
}
-
- // Connect the new EN and DATA signals and remove the old write port.
-
- cell->setPort(ID::EN, merged_en);
- cell->setPort(ID::DATA, merged_data);
-
- module->remove(wr_ports[last_i]);
- wr_ports[last_i] = NULL;
-
- log(" Active bits: ");
- std::vector<RTLIL::SigBit> en_bits = sigmap(cell->getPort(ID::EN));
- active_bits_on_port.push_back(std::vector<bool>(en_bits.size()));
- for (int k = int(en_bits.size())-1; k >= 0; k--)
- log("%c", active_bits_on_port[i][k] ? '1' : '0');
- log("\n");
+ changed = true;
+ port2.removed = true;
}
-
- last_port_by_addr[addr] = i;
}
- // Clean up `wr_ports': remove all NULL entries
-
- std::vector<RTLIL::Cell*> wr_ports_with_nulls;
- wr_ports_with_nulls.swap(wr_ports);
+ if (changed)
+ mem.emit();
- for (auto cell : wr_ports_with_nulls)
- if (cell != NULL)
- wr_ports.push_back(cell);
+ return changed;
}
@@ -486,178 +279,174 @@ struct MemoryShareWorker
// Consolidate write ports using sat-based resource sharing
// --------------------------------------------------------
- void consolidate_wr_using_sat(std::string memid, std::vector<RTLIL::Cell*> &wr_ports)
+ void consolidate_wr_using_sat(Mem &mem)
{
- if (wr_ports.size() <= 1)
+ if (GetSize(mem.wr_ports) <= 1)
return;
- ezSatPtr ez;
- SatGen satgen(ez.get(), &modwalker.sigmap);
+ // Get a list of ports that have any chance of being mergeable.
- // find list of considered ports and port pairs
+ pool<int> eligible_ports;
- std::set<int> considered_ports;
- std::set<int> considered_port_pairs;
-
- for (int i = 0; i < int(wr_ports.size()); i++) {
- std::vector<RTLIL::SigBit> bits = modwalker.sigmap(wr_ports[i]->getPort(ID::EN));
+ for (int i = 0; i < GetSize(mem.wr_ports); i++) {
+ auto &port = mem.wr_ports[i];
+ std::vector<RTLIL::SigBit> bits = modwalker.sigmap(port.en);
for (auto bit : bits)
if (bit == RTLIL::State::S1)
goto port_is_always_active;
- if (modwalker.has_drivers(bits))
- considered_ports.insert(i);
+ eligible_ports.insert(i);
port_is_always_active:;
}
- log("Consolidating write ports of memory %s.%s using sat-based resource sharing:\n", log_id(module), log_id(memid));
+ if (eligible_ports.size() <= 1)
+ return;
+
+ log("Consolidating write ports of memory %s.%s using sat-based resource sharing:\n", log_id(module), log_id(mem.memid));
- bool cache_clk_enable = false;
- bool cache_clk_polarity = false;
- RTLIL::SigSpec cache_clk;
+ // Group eligible ports by clock domain and width.
- for (int i = 0; i < int(wr_ports.size()); i++)
+ pool<int> checked_ports;
+ std::vector<std::vector<int>> groups;
+ for (int i = 0; i < GetSize(mem.wr_ports); i++)
{
- RTLIL::Cell *cell = wr_ports.at(i);
+ auto &port1 = mem.wr_ports[i];
+ if (!eligible_ports.count(i))
+ continue;
+ if (checked_ports.count(i))
+ continue;
- if (cell->parameters.at(ID::CLK_ENABLE).as_bool() != cache_clk_enable ||
- (cache_clk_enable && (sigmap(cell->getPort(ID::CLK)) != cache_clk ||
- cell->parameters.at(ID::CLK_POLARITY).as_bool() != cache_clk_polarity)))
+ std::vector<int> group;
+ group.push_back(i);
+
+ for (int j = i + 1; j < GetSize(mem.wr_ports); j++)
{
- cache_clk_enable = cell->parameters.at(ID::CLK_ENABLE).as_bool();
- cache_clk_polarity = cell->parameters.at(ID::CLK_POLARITY).as_bool();
- cache_clk = sigmap(cell->getPort(ID::CLK));
+ auto &port2 = mem.wr_ports[j];
+ if (!eligible_ports.count(j))
+ continue;
+ if (checked_ports.count(j))
+ continue;
+ if (port1.clk_enable != port2.clk_enable)
+ continue;
+ if (port1.clk_enable) {
+ if (port1.clk != port2.clk)
+ continue;
+ if (port1.clk_polarity != port2.clk_polarity)
+ continue;
+ }
+ if (port1.wide_log2 != port2.wide_log2)
+ continue;
+ group.push_back(j);
}
- else if (i > 0 && considered_ports.count(i-1) && considered_ports.count(i))
- considered_port_pairs.insert(i);
-
- if (cache_clk_enable)
- log(" Port %d (%s) on %s %s: %s\n", i, log_id(cell),
- cache_clk_polarity ? "posedge" : "negedge", log_signal(cache_clk),
- considered_ports.count(i) ? "considered" : "not considered");
- else
- log(" Port %d (%s) unclocked: %s\n", i, log_id(cell),
- considered_ports.count(i) ? "considered" : "not considered");
- }
- if (considered_port_pairs.size() < 1) {
- log(" No two subsequent ports in same clock domain considered -> nothing to consolidate.\n");
- return;
- }
-
- // create SAT representation of common input cone of all considered EN signals
+ for (auto j : group)
+ checked_ports.insert(j);
- pool<Wire*> one_hot_wires;
- std::set<RTLIL::Cell*> sat_cells;
- std::set<RTLIL::SigBit> bits_queue;
- std::map<int, int> port_to_sat_variable;
+ if (group.size() <= 1)
+ continue;
- for (int i = 0; i < int(wr_ports.size()); i++)
- if (considered_port_pairs.count(i) || considered_port_pairs.count(i+1))
- {
- RTLIL::SigSpec sig = modwalker.sigmap(wr_ports[i]->getPort(ID::EN));
- port_to_sat_variable[i] = ez->expression(ez->OpOr, satgen.importSigSpec(sig));
+ groups.push_back(group);
+ }
- std::vector<RTLIL::SigBit> bits = sig;
- bits_queue.insert(bits.begin(), bits.end());
+ bool changed = false;
+ for (auto &group : groups) {
+ auto &some_port = mem.wr_ports[group[0]];
+ string ports;
+ for (auto idx : group) {
+ if (idx != group[0])
+ ports += ", ";
+ ports += std::to_string(idx);
+ }
+ if (!some_port.clk_enable) {
+ log(" Checking unclocked group, width %d: ports %s.\n", mem.width << some_port.wide_log2, ports.c_str());
+ } else {
+ log(" Checking group clocked with %sedge %s, width %d: ports %s.\n", some_port.clk_polarity ? "pos" : "neg", log_signal(some_port.clk), mem.width << some_port.wide_log2, ports.c_str());
}
- while (!bits_queue.empty())
- {
- for (auto bit : bits_queue)
- if (bit.wire && bit.wire->get_bool_attribute(ID::onehot))
- one_hot_wires.insert(bit.wire);
-
- pool<ModWalker::PortBit> portbits;
- modwalker.get_drivers(portbits, bits_queue);
- bits_queue.clear();
-
- for (auto &pbit : portbits)
- if (sat_cells.count(pbit.cell) == 0 && cone_ct.cell_known(pbit.cell->type)) {
- pool<RTLIL::SigBit> &cell_inputs = modwalker.cell_inputs[pbit.cell];
- bits_queue.insert(cell_inputs.begin(), cell_inputs.end());
- sat_cells.insert(pbit.cell);
- }
- }
+ // Okay, time to actually run the SAT solver.
- for (auto wire : one_hot_wires) {
- log(" Adding one-hot constraint for wire %s.\n", log_id(wire));
- vector<int> ez_wire_bits = satgen.importSigSpec(wire);
- for (int i : ez_wire_bits)
- for (int j : ez_wire_bits)
- if (i != j) ez->assume(ez->NOT(i), j);
- }
+ QuickConeSat qcsat(modwalker);
- log(" Common input cone for all EN signals: %d cells.\n", int(sat_cells.size()));
+ // create SAT representation of common input cone of all considered EN signals
- for (auto cell : sat_cells)
- satgen.importCell(cell);
+ dict<int, int> port_to_sat_variable;
- log(" Size of unconstrained SAT problem: %d variables, %d clauses\n", ez->numCnfVariables(), ez->numCnfClauses());
+ for (auto idx : group)
+ port_to_sat_variable[idx] = qcsat.ez->expression(qcsat.ez->OpOr, qcsat.importSig(mem.wr_ports[idx].en));
- // merge subsequent ports if possible
+ qcsat.prepare();
- for (int i = 0; i < int(wr_ports.size()); i++)
- {
- if (!considered_port_pairs.count(i))
- continue;
+ log(" Common input cone for all EN signals: %d cells.\n", GetSize(qcsat.imported_cells));
- if (ez->solve(port_to_sat_variable.at(i-1), port_to_sat_variable.at(i))) {
- log(" According to SAT solver sharing of port %d with port %d is not possible.\n", i-1, i);
- continue;
- }
+ log(" Size of unconstrained SAT problem: %d variables, %d clauses\n", qcsat.ez->numCnfVariables(), qcsat.ez->numCnfClauses());
+
+ // now try merging the ports.
+
+ for (int ii = 0; ii < GetSize(group); ii++) {
+ int idx1 = group[ii];
+ auto &port1 = mem.wr_ports[idx1];
+ if (port1.removed)
+ continue;
+ for (int jj = ii + 1; jj < GetSize(group); jj++) {
+ int idx2 = group[jj];
+ auto &port2 = mem.wr_ports[idx2];
+ if (port2.removed)
+ continue;
- log(" Merging port %d into port %d.\n", i-1, i);
- port_to_sat_variable.at(i) = ez->OR(port_to_sat_variable.at(i-1), port_to_sat_variable.at(i));
+ if (qcsat.ez->solve(port_to_sat_variable.at(idx1), port_to_sat_variable.at(idx2))) {
+ log(" According to SAT solver sharing of port %d with port %d is not possible.\n", idx1, idx2);
+ continue;
+ }
- RTLIL::SigSpec last_addr = wr_ports[i-1]->getPort(ID::ADDR);
- RTLIL::SigSpec last_data = wr_ports[i-1]->getPort(ID::DATA);
- std::vector<RTLIL::SigBit> last_en = modwalker.sigmap(wr_ports[i-1]->getPort(ID::EN));
+ log(" Merging port %d into port %d.\n", idx2, idx1);
+ mem.prepare_wr_merge(idx1, idx2, &initvals);
+ port_to_sat_variable.at(idx1) = qcsat.ez->OR(port_to_sat_variable.at(idx1), port_to_sat_variable.at(idx2));
- RTLIL::SigSpec this_addr = wr_ports[i]->getPort(ID::ADDR);
- RTLIL::SigSpec this_data = wr_ports[i]->getPort(ID::DATA);
- std::vector<RTLIL::SigBit> this_en = modwalker.sigmap(wr_ports[i]->getPort(ID::EN));
+ RTLIL::SigSpec last_addr = port1.addr;
+ RTLIL::SigSpec last_data = port1.data;
+ std::vector<RTLIL::SigBit> last_en = modwalker.sigmap(port1.en);
- RTLIL::SigBit this_en_active = module->ReduceOr(NEW_ID, this_en);
+ RTLIL::SigSpec this_addr = port2.addr;
+ RTLIL::SigSpec this_data = port2.data;
+ std::vector<RTLIL::SigBit> this_en = modwalker.sigmap(port2.en);
- if (GetSize(last_addr) < GetSize(this_addr))
- last_addr.extend_u0(GetSize(this_addr));
- else
- this_addr.extend_u0(GetSize(last_addr));
+ RTLIL::SigBit this_en_active = module->ReduceOr(NEW_ID, this_en);
- wr_ports[i]->setParam(ID::ABITS, GetSize(this_addr));
- wr_ports[i]->setPort(ID::ADDR, module->Mux(NEW_ID, last_addr, this_addr, this_en_active));
- wr_ports[i]->setPort(ID::DATA, module->Mux(NEW_ID, last_data, this_data, this_en_active));
+ if (GetSize(last_addr) < GetSize(this_addr))
+ last_addr.extend_u0(GetSize(this_addr));
+ else
+ this_addr.extend_u0(GetSize(last_addr));
- std::map<std::pair<RTLIL::SigBit, RTLIL::SigBit>, int> groups_en;
- RTLIL::SigSpec grouped_last_en, grouped_this_en, en;
- RTLIL::Wire *grouped_en = module->addWire(NEW_ID, 0);
+ SigSpec new_addr = module->Mux(NEW_ID, last_addr.extract_end(port1.wide_log2), this_addr.extract_end(port1.wide_log2), this_en_active);
- for (int j = 0; j < int(this_en.size()); j++) {
- std::pair<RTLIL::SigBit, RTLIL::SigBit> key(last_en[j], this_en[j]);
- if (!groups_en.count(key)) {
- grouped_last_en.append(last_en[j]);
- grouped_this_en.append(this_en[j]);
- groups_en[key] = grouped_en->width;
- grouped_en->width++;
- }
- en.append(RTLIL::SigSpec(grouped_en, groups_en[key]));
- }
+ port1.addr = SigSpec({new_addr, port1.addr.extract(0, port1.wide_log2)});
+ port1.data = module->Mux(NEW_ID, last_data, this_data, this_en_active);
- module->addMux(NEW_ID, grouped_last_en, grouped_this_en, this_en_active, grouped_en);
- wr_ports[i]->setPort(ID::EN, en);
+ std::map<std::pair<RTLIL::SigBit, RTLIL::SigBit>, int> groups_en;
+ RTLIL::SigSpec grouped_last_en, grouped_this_en, en;
+ RTLIL::Wire *grouped_en = module->addWire(NEW_ID, 0);
- module->remove(wr_ports[i-1]);
- wr_ports[i-1] = NULL;
- }
+ for (int j = 0; j < int(this_en.size()); j++) {
+ std::pair<RTLIL::SigBit, RTLIL::SigBit> key(last_en[j], this_en[j]);
+ if (!groups_en.count(key)) {
+ grouped_last_en.append(last_en[j]);
+ grouped_this_en.append(this_en[j]);
+ groups_en[key] = grouped_en->width;
+ grouped_en->width++;
+ }
+ en.append(RTLIL::SigSpec(grouped_en, groups_en[key]));
+ }
- // Clean up `wr_ports': remove all NULL entries
+ module->addMux(NEW_ID, grouped_last_en, grouped_this_en, this_en_active, grouped_en);
+ port1.en = en;
- std::vector<RTLIL::Cell*> wr_ports_with_nulls;
- wr_ports_with_nulls.swap(wr_ports);
+ port2.removed = true;
+ changed = true;
+ }
+ }
+ }
- for (auto cell : wr_ports_with_nulls)
- if (cell != NULL)
- wr_ports.push_back(cell);
+ if (changed)
+ mem.emit();
}
@@ -665,26 +454,19 @@ struct MemoryShareWorker
// Setup and run
// -------------
- MemoryShareWorker(RTLIL::Design *design) : design(design), modwalker(design) {}
+ MemoryShareWorker(RTLIL::Design *design, bool flag_widen, bool flag_sat) : design(design), modwalker(design), flag_widen(flag_widen), flag_sat(flag_sat) {}
void operator()(RTLIL::Module* module)
{
- std::map<std::string, std::pair<std::vector<RTLIL::Cell*>, std::vector<RTLIL::Cell*>>> memindex;
+ std::vector<Mem> memories = Mem::get_selected_memories(module);
this->module = module;
sigmap.set(module);
- sig_to_mux.clear();
- conditions_logic_cache.clear();
+ initvals.set(&sigmap, module);
sigmap_xmux = sigmap;
for (auto cell : module->cells())
{
- if (cell->type == ID($memrd))
- memindex[cell->parameters.at(ID::MEMID).decode_string()].first.push_back(cell);
-
- if (cell->type == ID($memwr))
- memindex[cell->parameters.at(ID::MEMID).decode_string()].second.push_back(cell);
-
if (cell->type == ID($mux))
{
RTLIL::SigSpec sig_a = sigmap_xmux(cell->getPort(ID::A));
@@ -695,40 +477,20 @@ struct MemoryShareWorker
else if (sig_b.is_fully_undef())
sigmap_xmux.add(cell->getPort(ID::Y), sig_a);
}
-
- if (cell->type.in(ID($mux), ID($pmux)))
- {
- std::vector<RTLIL::SigBit> sig_y = sigmap(cell->getPort(ID::Y));
- for (int i = 0; i < int(sig_y.size()); i++)
- sig_to_mux[sig_y[i]] = std::pair<RTLIL::Cell*, int>(cell, i);
- }
}
- for (auto &it : memindex) {
- std::sort(it.second.first.begin(), it.second.first.end(), memcells_cmp);
- std::sort(it.second.second.begin(), it.second.second.end(), memcells_cmp);
- translate_rd_feedback_to_en(it.first, it.second.first, it.second.second);
- consolidate_wr_by_addr(it.first, it.second.second);
+ for (auto &mem : memories) {
+ while (consolidate_rd_by_addr(mem));
+ while (consolidate_wr_by_addr(mem));
}
- cone_ct.setup_internals();
- cone_ct.cell_types.erase(ID($mul));
- cone_ct.cell_types.erase(ID($mod));
- cone_ct.cell_types.erase(ID($div));
- cone_ct.cell_types.erase(ID($modfloor));
- cone_ct.cell_types.erase(ID($divfloor));
- cone_ct.cell_types.erase(ID($pow));
- cone_ct.cell_types.erase(ID($shl));
- cone_ct.cell_types.erase(ID($shr));
- cone_ct.cell_types.erase(ID($sshl));
- cone_ct.cell_types.erase(ID($sshr));
- cone_ct.cell_types.erase(ID($shift));
- cone_ct.cell_types.erase(ID($shiftx));
-
- modwalker.setup(module, &cone_ct);
-
- for (auto &it : memindex)
- consolidate_wr_using_sat(it.first, it.second.second);
+ if (!flag_sat)
+ return;
+
+ modwalker.setup(module);
+
+ for (auto &mem : memories)
+ consolidate_wr_using_sat(mem);
}
};
@@ -738,22 +500,22 @@ struct MemorySharePass : public Pass {
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" memory_share [selection]\n");
+ log(" memory_share [-nosat] [-nowiden] [selection]\n");
log("\n");
log("This pass merges share-able memory ports into single memory ports.\n");
log("\n");
log("The following methods are used to consolidate the number of memory ports:\n");
log("\n");
- log(" - When write ports are connected to async read ports accessing the same\n");
- log(" address, then this feedback path is converted to a write port with\n");
- log(" byte/part enable signals.\n");
- log("\n");
log(" - When multiple write ports access the same address then this is converted\n");
log(" to a single write port with a more complex data and/or enable logic path.\n");
log("\n");
+ log(" - When multiple read or write ports access adjacent aligned addresses, they are\n");
+ log(" merged to a single wide read or write port. This transformation can be\n");
+ log(" disabled with the \"-nowiden\" option.\n");
+ log("\n");
log(" - When multiple write ports are never accessed at the same time (a SAT\n");
log(" solver is used to determine this), then the ports are merged into a single\n");
- log(" write port.\n");
+ log(" write port. This transformation can be disabled with the \"-nosat\" option.\n");
log("\n");
log("Note that in addition to the algorithms implemented in this pass, the $memrd\n");
log("and $memwr cells are also subject to generic resource sharing passes (and other\n");
@@ -761,9 +523,26 @@ struct MemorySharePass : public Pass {
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override {
+ bool flag_widen = true;
+ bool flag_sat = true;
log_header(design, "Executing MEMORY_SHARE pass (consolidating $memrd/$memwr cells).\n");
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-nosat")
+ {
+ flag_sat = false;
+ continue;
+ }
+ if (args[argidx] == "-nowiden")
+ {
+ flag_widen = false;
+ continue;
+ }
+ break;
+ }
extra_args(args, 1, design);
- MemoryShareWorker msw(design);
+ MemoryShareWorker msw(design, flag_widen, flag_sat);
for (auto module : design->selected_modules())
msw(module);
diff --git a/passes/memory/memory_unpack.cc b/passes/memory/memory_unpack.cc
index 16b57d9c3..422d6fe15 100644
--- a/passes/memory/memory_unpack.cc
+++ b/passes/memory/memory_unpack.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc
index 4ae9b8895..4e52ad8da 100644
--- a/passes/opt/Makefile.inc
+++ b/passes/opt/Makefile.inc
@@ -2,6 +2,9 @@
OBJS += passes/opt/opt.o
OBJS += passes/opt/opt_merge.o
OBJS += passes/opt/opt_mem.o
+OBJS += passes/opt/opt_mem_feedback.o
+OBJS += passes/opt/opt_mem_priority.o
+OBJS += passes/opt/opt_mem_widen.o
OBJS += passes/opt/opt_muxtree.o
OBJS += passes/opt/opt_reduce.o
OBJS += passes/opt/opt_dff.o
diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc
index aa5f82437..b5e151098 100644
--- a/passes/opt/muxpack.cc
+++ b/passes/opt/muxpack.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/opt/opt.cc b/passes/opt/opt.cc
index 4b052d9a2..c3e418c07 100644
--- a/passes/opt/opt.cc
+++ b/passes/opt/opt.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc
index 883374cf6..cb2c261c4 100644
--- a/passes/opt/opt_clean.cc
+++ b/passes/opt/opt_clean.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -21,6 +21,7 @@
#include "kernel/sigtools.h"
#include "kernel/log.h"
#include "kernel/celltypes.h"
+#include "kernel/ffinit.h"
#include <stdlib.h>
#include <stdio.h>
#include <set>
@@ -101,6 +102,7 @@ void rmunused_module_cells(Module *module, bool verbose)
pool<SigBit> used_raw_bits;
dict<SigBit, pool<Cell*>> wire2driver;
dict<SigBit, vector<string>> driver_driver_logs;
+ FfInitVals ffinit(&sigmap, module);
SigMap raw_sigmap;
for (auto &it : module->connections_) {
@@ -115,7 +117,7 @@ void rmunused_module_cells(Module *module, bool verbose)
}
for (Cell *cell : module->cells()) {
- if (cell->type.in(ID($memwr), ID($meminit))) {
+ if (cell->type.in(ID($memwr), ID($memwr_v2), ID($meminit), ID($meminit_v2))) {
IdString mem_id = cell->getParam(ID::MEMID).decode_string();
mem2cells[mem_id].insert(cell);
}
@@ -165,7 +167,7 @@ void rmunused_module_cells(Module *module, bool verbose)
for (auto bit : sigmap(it.second))
bits.insert(bit);
- if (cell->type == ID($memrd)) {
+ if (cell->type.in(ID($memrd), ID($memrd_v2))) {
IdString mem_id = cell->getParam(ID::MEMID).decode_string();
if (mem_unused.count(mem_id)) {
mem_unused.erase(mem_id);
@@ -193,6 +195,8 @@ void rmunused_module_cells(Module *module, bool verbose)
if (verbose)
log_debug(" removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str());
module->design->scratchpad_set_bool("opt.did_something", true);
+ if (RTLIL::builtin_ff_cell_types().count(cell->type))
+ ffinit.remove_init(cell->getPort(ID::Q));
module->remove(cell);
count_rm_cells++;
}
@@ -335,6 +339,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
used_signals_nodrivers.add(it2.second);
}
}
+ dict<RTLIL::SigBit, RTLIL::State> init_bits;
for (auto &it : module->wires_) {
RTLIL::Wire *wire = it.second;
if (wire->port_id > 0) {
@@ -350,6 +355,29 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos
assign_map.apply(sig);
used_signals.add(sig);
}
+ auto it2 = wire->attributes.find(ID::init);
+ if (it2 != wire->attributes.end()) {
+ RTLIL::Const &val = it2->second;
+ SigSpec sig = assign_map(wire);
+ for (int i = 0; i < GetSize(val) && i < GetSize(sig); i++)
+ if (val.bits[i] != State::Sx)
+ init_bits[sig[i]] = val.bits[i];
+ wire->attributes.erase(it2);
+ }
+ }
+
+ for (auto wire : module->wires()) {
+ bool found = false;
+ Const val(State::Sx, wire->width);
+ for (int i = 0; i < wire->width; i++) {
+ auto it = init_bits.find(RTLIL::SigBit(wire, i));
+ if (it != init_bits.end()) {
+ val.bits[i] = it->second;
+ found = true;
+ }
+ }
+ if (found)
+ wire->attributes[ID::init] = val;
}
pool<RTLIL::Wire*> del_wires_queue;
diff --git a/passes/opt/opt_demorgan.cc b/passes/opt/opt_demorgan.cc
index f0fa86f42..1464c4177 100644
--- a/passes/opt/opt_demorgan.cc
+++ b/passes/opt/opt_demorgan.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/opt/opt_dff.cc b/passes/opt/opt_dff.cc
index a47071a30..73d674c8d 100644
--- a/passes/opt/opt_dff.cc
+++ b/passes/opt/opt_dff.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2020 Marcelina Kościelnicka <mwk@0x04.net>
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -21,7 +21,8 @@
#include "kernel/log.h"
#include "kernel/register.h"
#include "kernel/rtlil.h"
-#include "kernel/satgen.h"
+#include "kernel/qcsat.h"
+#include "kernel/modtools.h"
#include "kernel/sigtools.h"
#include "kernel/ffinit.h"
#include "kernel/ff.h"
@@ -51,26 +52,20 @@ struct OptDffWorker
FfInitVals initvals;
dict<SigBit, int> bitusers;
dict<SigBit, cell_int_t> bit2mux;
- dict<SigBit, RTLIL::Cell*> bit2driver;
typedef std::map<RTLIL::SigBit, bool> pattern_t;
typedef std::set<pattern_t> patterns_t;
typedef std::pair<RTLIL::SigBit, bool> ctrl_t;
typedef std::set<ctrl_t> ctrls_t;
- ezSatPtr ez;
- SatGen satgen;
- pool<Cell*> sat_cells;
-
// Used as a queue.
std::vector<Cell *> dff_cells;
- OptDffWorker(const OptDffOptions &opt, Module *mod) : opt(opt), module(mod), sigmap(mod), initvals(&sigmap, mod), ez(), satgen(ez.get(), &sigmap) {
- // Gathering three kinds of information here for every sigmapped SigBit:
+ OptDffWorker(const OptDffOptions &opt, Module *mod) : opt(opt), module(mod), sigmap(mod), initvals(&sigmap, mod) {
+ // Gathering two kinds of information here for every sigmapped SigBit:
//
// - bitusers: how many users it has (muxes will only be merged into FFs if this is 1, making the FF the only user)
// - bit2mux: the mux cell and bit index that drives it, if any
- // - bit2driver: the cell driving it, if any
for (auto wire : module->wires())
{
@@ -88,10 +83,6 @@ struct OptDffWorker
for (auto conn : cell->connections()) {
bool is_output = cell->output(conn.first);
- if (is_output) {
- for (auto bit : sigmap(conn.second))
- bit2driver[bit] = cell;
- }
if (!is_output || !cell->known()) {
for (auto bit : sigmap(conn.second))
bitusers[bit]++;
@@ -104,20 +95,6 @@ struct OptDffWorker
}
- std::function<void(Cell*)> sat_import_cell = [&](Cell *c) {
- if (!sat_cells.insert(c).second)
- return;
- if (!satgen.importCell(c))
- return;
- for (auto &conn : c->connections()) {
- if (!c->input(conn.first))
- continue;
- for (auto bit : sigmap(conn.second))
- if (bit2driver.count(bit))
- sat_import_cell(bit2driver.at(bit));
- }
- };
-
State combine_const(State a, State b) {
if (a == State::Sx && !opt.keepdc)
return b;
@@ -295,7 +272,7 @@ struct OptDffWorker
bool changed = false;
if (!ff.width) {
- module->remove(cell);
+ ff.remove();
did_something = true;
continue;
}
@@ -318,9 +295,9 @@ struct OptDffWorker
if (!ff.pol_clr) {
module->connect(ff.sig_q[i], ff.sig_clr[i]);
} else if (ff.is_fine) {
- module->addNotGate(NEW_ID, ff.sig_q[i], ff.sig_clr[i]);
+ module->addNotGate(NEW_ID, ff.sig_clr[i], ff.sig_q[i]);
} else {
- module->addNot(NEW_ID, ff.sig_q[i], ff.sig_clr[i]);
+ module->addNot(NEW_ID, ff.sig_clr[i], ff.sig_q[i]);
}
log("Handling always-active SET at position %d on %s (%s) from module %s (changing to combinatorial circuit).\n",
i, log_id(cell), log_id(cell->type), log_id(module));
@@ -336,6 +313,7 @@ struct OptDffWorker
continue;
}
ff = ff.slice(keep_bits);
+ ff.cell = cell;
changed = true;
}
@@ -402,6 +380,68 @@ struct OptDffWorker
}
}
+ if (ff.has_aload) {
+ if (ff.sig_aload == (ff.pol_aload ? State::S0 : State::S1) || (!opt.keepdc && ff.sig_aload == State::Sx)) {
+ // Always-inactive enable — remove.
+ log("Removing never-active async load on %s (%s) from module %s.\n",
+ log_id(cell), log_id(cell->type), log_id(module));
+ ff.has_aload = false;
+ changed = true;
+ } else if (ff.sig_aload == (ff.pol_aload ? State::S1 : State::S0)) {
+ // Always-active enable. Make a comb circuit, nuke the FF/latch.
+ log("Handling always-active async load on %s (%s) from module %s (changing to combinatorial circuit).\n",
+ log_id(cell), log_id(cell->type), log_id(module));
+ ff.remove();
+ if (ff.has_sr) {
+ SigSpec tmp;
+ if (ff.is_fine) {
+ if (ff.pol_set)
+ tmp = module->MuxGate(NEW_ID, ff.sig_ad, State::S1, ff.sig_set);
+ else
+ tmp = module->MuxGate(NEW_ID, State::S1, ff.sig_ad, ff.sig_set);
+ if (ff.pol_clr)
+ module->addMuxGate(NEW_ID, tmp, State::S0, ff.sig_clr, ff.sig_q);
+ else
+ module->addMuxGate(NEW_ID, State::S0, tmp, ff.sig_clr, ff.sig_q);
+ } else {
+ if (ff.pol_set)
+ tmp = module->Or(NEW_ID, ff.sig_ad, ff.sig_set);
+ else
+ tmp = module->Or(NEW_ID, ff.sig_ad, module->Not(NEW_ID, ff.sig_set));
+ if (ff.pol_clr)
+ module->addAnd(NEW_ID, tmp, module->Not(NEW_ID, ff.sig_clr), ff.sig_q);
+ else
+ module->addAnd(NEW_ID, tmp, ff.sig_clr, ff.sig_q);
+ }
+ } else if (ff.has_arst) {
+ if (ff.is_fine) {
+ if (ff.pol_arst)
+ module->addMuxGate(NEW_ID, ff.sig_ad, ff.val_arst[0], ff.sig_arst, ff.sig_q);
+ else
+ module->addMuxGate(NEW_ID, ff.val_arst[0], ff.sig_ad, ff.sig_arst, ff.sig_q);
+ } else {
+ if (ff.pol_arst)
+ module->addMux(NEW_ID, ff.sig_ad, ff.val_arst, ff.sig_arst, ff.sig_q);
+ else
+ module->addMux(NEW_ID, ff.val_arst, ff.sig_ad, ff.sig_arst, ff.sig_q);
+ }
+ } else {
+ module->connect(ff.sig_q, ff.sig_ad);
+ }
+ did_something = true;
+ continue;
+ } else if (ff.sig_ad.is_fully_const() && !ff.has_arst && !ff.has_sr) {
+ log("Changing const-value async load to async reset on %s (%s) from module %s.\n",
+ log_id(cell), log_id(cell->type), log_id(module));
+ ff.has_arst = true;
+ ff.has_aload = false;
+ ff.sig_arst = ff.sig_aload;
+ ff.pol_arst = ff.pol_aload;
+ ff.val_arst = ff.sig_ad.as_const();
+ changed = true;
+ }
+ }
+
if (ff.has_arst) {
if (ff.sig_arst == (ff.pol_arst ? State::S0 : State::S1)) {
// Always-inactive reset — remove.
@@ -413,8 +453,7 @@ struct OptDffWorker
// Always-active async reset — change to const driver.
log("Handling always-active ARST on %s (%s) from module %s (changing to const driver).\n",
log_id(cell), log_id(cell->type), log_id(module));
- initvals.remove_init(ff.sig_q);
- module->remove(cell);
+ ff.remove();
module->connect(ff.sig_q, ff.val_arst);
did_something = true;
continue;
@@ -434,111 +473,63 @@ struct OptDffWorker
log_id(cell), log_id(cell->type), log_id(module));
ff.has_srst = false;
if (!ff.ce_over_srst)
- ff.has_en = false;
- ff.sig_d = ff.val_d = ff.val_srst;
- ff.d_is_const = true;
+ ff.has_ce = false;
+ ff.sig_d = ff.val_srst;
changed = true;
}
}
- if (ff.has_en) {
- if (ff.sig_en == (ff.pol_en ? State::S0 : State::S1) || (!opt.keepdc && ff.sig_en == State::Sx)) {
+ if (ff.has_ce) {
+ if (ff.sig_ce == (ff.pol_ce ? State::S0 : State::S1) || (!opt.keepdc && ff.sig_ce == State::Sx)) {
// Always-inactive enable — remove.
- if (ff.has_clk && ff.has_srst && !ff.ce_over_srst) {
+ if (ff.has_srst && !ff.ce_over_srst) {
log("Handling never-active EN on %s (%s) from module %s (connecting SRST instead).\n",
log_id(cell), log_id(cell->type), log_id(module));
// FF with sync reset — connect the sync reset to D instead.
- ff.pol_en = ff.pol_srst;
- ff.sig_en = ff.sig_srst;
+ ff.pol_ce = ff.pol_srst;
+ ff.sig_ce = ff.sig_srst;
ff.has_srst = false;
- ff.sig_d = ff.val_d = ff.val_srst;
- ff.d_is_const = true;
+ ff.sig_d = ff.val_srst;
changed = true;
} else {
log("Handling never-active EN on %s (%s) from module %s (removing D path).\n",
log_id(cell), log_id(cell->type), log_id(module));
- // The D input path is effectively useless, so remove it (this will be a const-input D latch, SR latch, or a const driver).
- ff.has_d = ff.has_en = ff.has_clk = false;
+ // The D input path is effectively useless, so remove it (this will be a D latch, SR latch, or a const driver).
+ ff.has_ce = ff.has_clk = ff.has_srst = false;
changed = true;
}
- } else if (ff.sig_en == (ff.pol_en ? State::S1 : State::S0)) {
- // Always-active enable.
- if (ff.has_clk) {
- // For FF, just remove the useless enable.
- log("Removing always-active EN on %s (%s) from module %s.\n",
- log_id(cell), log_id(cell->type), log_id(module));
- ff.has_en = false;
- changed = true;
- } else {
- // For latches, make a comb circuit, nuke the latch.
- log("Handling always-active EN on %s (%s) from module %s (changing to combinatorial circuit).\n",
- log_id(cell), log_id(cell->type), log_id(module));
- initvals.remove_init(ff.sig_q);
- module->remove(cell);
- if (ff.has_sr) {
- SigSpec tmp;
- if (ff.is_fine) {
- if (ff.pol_set)
- tmp = module->MuxGate(NEW_ID, ff.sig_d, State::S1, ff.sig_set);
- else
- tmp = module->MuxGate(NEW_ID, State::S1, ff.sig_d, ff.sig_set);
- if (ff.pol_clr)
- module->addMuxGate(NEW_ID, tmp, State::S0, ff.sig_clr, ff.sig_q);
- else
- module->addMuxGate(NEW_ID, State::S0, tmp, ff.sig_clr, ff.sig_q);
- } else {
- if (ff.pol_set)
- tmp = module->Or(NEW_ID, ff.sig_d, ff.sig_set);
- else
- tmp = module->Or(NEW_ID, ff.sig_d, module->Not(NEW_ID, ff.sig_set));
- if (ff.pol_clr)
- module->addAnd(NEW_ID, tmp, module->Not(NEW_ID, ff.sig_clr), ff.sig_q);
- else
- module->addAnd(NEW_ID, tmp, ff.sig_clr, ff.sig_q);
- }
- } else if (ff.has_arst) {
- if (ff.is_fine) {
- if (ff.pol_arst)
- module->addMuxGate(NEW_ID, ff.sig_d, ff.val_arst[0], ff.sig_arst, ff.sig_q);
- else
- module->addMuxGate(NEW_ID, ff.val_arst[0], ff.sig_d, ff.sig_arst, ff.sig_q);
- } else {
- if (ff.pol_arst)
- module->addMux(NEW_ID, ff.sig_d, ff.val_arst, ff.sig_arst, ff.sig_q);
- else
- module->addMux(NEW_ID, ff.val_arst, ff.sig_d, ff.sig_arst, ff.sig_q);
- }
- } else {
- module->connect(ff.sig_q, ff.sig_d);
- }
- did_something = true;
- continue;
- }
+ } else if (ff.sig_ce == (ff.pol_ce ? State::S1 : State::S0)) {
+ // Always-active enable. Just remove it.
+ // For FF, just remove the useless enable.
+ log("Removing always-active EN on %s (%s) from module %s.\n",
+ log_id(cell), log_id(cell->type), log_id(module));
+ ff.has_ce = false;
+ changed = true;
}
}
if (ff.has_clk) {
if (ff.sig_clk.is_fully_const()) {
- // Const clock — the D input path is effectively useless, so remove it (this will be a const-input D latch, SR latch, or a const driver).
+ // Const clock — the D input path is effectively useless, so remove it (this will be a D latch, SR latch, or a const driver).
log("Handling const CLK on %s (%s) from module %s (removing D path).\n",
log_id(cell), log_id(cell->type), log_id(module));
- ff.has_d = ff.has_en = ff.has_clk = ff.has_srst = false;
+ ff.has_ce = ff.has_clk = ff.has_srst = false;
changed = true;
}
}
- if (ff.has_d && ff.sig_d == ff.sig_q) {
+ if ((ff.has_clk || ff.has_gclk) && ff.sig_d == ff.sig_q) {
// Q wrapped back to D, can be removed.
if (ff.has_clk && ff.has_srst) {
// FF with sync reset — connect the sync reset to D instead.
log("Handling D = Q on %s (%s) from module %s (conecting SRST instead).\n",
log_id(cell), log_id(cell->type), log_id(module));
- if (ff.has_en && ff.ce_over_srst) {
- if (!ff.pol_en) {
+ if (ff.has_ce && ff.ce_over_srst) {
+ if (!ff.pol_ce) {
if (ff.is_fine)
- ff.sig_en = module->NotGate(NEW_ID, ff.sig_en);
+ ff.sig_ce = module->NotGate(NEW_ID, ff.sig_ce);
else
- ff.sig_en = module->Not(NEW_ID, ff.sig_en);
+ ff.sig_ce = module->Not(NEW_ID, ff.sig_ce);
}
if (!ff.pol_srst) {
if (ff.is_fine)
@@ -547,96 +538,37 @@ struct OptDffWorker
ff.sig_srst = module->Not(NEW_ID, ff.sig_srst);
}
if (ff.is_fine)
- ff.sig_en = module->AndGate(NEW_ID, ff.sig_en, ff.sig_srst);
+ ff.sig_ce = module->AndGate(NEW_ID, ff.sig_ce, ff.sig_srst);
else
- ff.sig_en = module->And(NEW_ID, ff.sig_en, ff.sig_srst);
- ff.pol_en = true;
+ ff.sig_ce = module->And(NEW_ID, ff.sig_ce, ff.sig_srst);
+ ff.pol_ce = true;
} else {
- ff.pol_en = ff.pol_srst;
- ff.sig_en = ff.sig_srst;
+ ff.pol_ce = ff.pol_srst;
+ ff.sig_ce = ff.sig_srst;
}
- ff.has_en = true;
+ ff.has_ce = true;
ff.has_srst = false;
- ff.sig_d = ff.val_d = ff.val_srst;
- ff.d_is_const = true;
+ ff.sig_d = ff.val_srst;
changed = true;
} else {
// The D input path is effectively useless, so remove it (this will be a const-input D latch, SR latch, or a const driver).
log("Handling D = Q on %s (%s) from module %s (removing D path).\n",
log_id(cell), log_id(cell->type), log_id(module));
- ff.has_d = ff.has_en = ff.has_clk = false;
+ ff.has_clk = ff.has_ce = false;
changed = true;
}
}
- // Now check if any bit can be replaced by a constant.
- pool<int> removed_sigbits;
- for (int i = 0; i < ff.width; i++) {
- State val = ff.val_init[i];
- if (ff.has_arst)
- val = combine_const(val, ff.val_arst[i]);
- if (ff.has_srst)
- val = combine_const(val, ff.val_srst[i]);
- if (ff.has_sr) {
- if (ff.sig_clr[i] != (ff.pol_clr ? State::S0 : State::S1))
- val = combine_const(val, State::S0);
- if (ff.sig_set[i] != (ff.pol_set ? State::S0 : State::S1))
- val = combine_const(val, State::S1);
- }
- if (val == State::Sm)
- continue;
- if (ff.has_d) {
- if (!ff.sig_d[i].wire) {
- val = combine_const(val, ff.sig_d[i].data);
- if (val == State::Sm)
- continue;
- } else {
- if (!opt.sat)
- continue;
- // For each register bit, try to prove that it cannot change from the initial value. If so, remove it
- if (!bit2driver.count(ff.sig_d[i]))
- continue;
- if (val != State::S0 && val != State::S1)
- continue;
-
- sat_import_cell(bit2driver.at(ff.sig_d[i]));
-
- int init_sat_pi = satgen.importSigSpec(val).front();
- int q_sat_pi = satgen.importSigBit(ff.sig_q[i]);
- int d_sat_pi = satgen.importSigBit(ff.sig_d[i]);
-
- // Try to find out whether the register bit can change under some circumstances
- bool counter_example_found = ez->solve(ez->IFF(q_sat_pi, init_sat_pi), ez->NOT(ez->IFF(d_sat_pi, init_sat_pi)));
-
- // If the register bit cannot change, we can replace it with a constant
- if (counter_example_found)
- continue;
- }
- }
- log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", val ? 1 : 0,
- i, log_id(cell), log_id(cell->type), log_id(module));
-
- initvals.remove_init(ff.sig_q[i]);
- module->connect(ff.sig_q[i], val);
- removed_sigbits.insert(i);
- }
- if (!removed_sigbits.empty()) {
- std::vector<int> keep_bits;
- for (int i = 0; i < ff.width; i++)
- if (!removed_sigbits.count(i))
- keep_bits.push_back(i);
- if (keep_bits.empty()) {
- module->remove(cell);
- did_something = true;
- continue;
- }
- ff = ff.slice(keep_bits);
+ if (ff.has_aload && !ff.has_clk && ff.sig_ad == ff.sig_q) {
+ log("Handling AD = Q on %s (%s) from module %s (removing async load path).\n",
+ log_id(cell), log_id(cell->type), log_id(module));
+ ff.has_aload = false;
changed = true;
}
// The cell has been simplified as much as possible already. Now try to spice it up with enables / sync resets.
if (ff.has_clk) {
- if (!ff.has_arst && !ff.has_sr && (!ff.has_srst || !ff.has_en || ff.ce_over_srst) && !opt.nosdff) {
+ if (!ff.has_arst && !ff.has_sr && (!ff.has_srst || !ff.has_ce || ff.ce_over_srst) && !opt.nosdff) {
// Try to merge sync resets.
std::map<ctrls_t, std::vector<int>> groups;
std::vector<int> remaining_indices;
@@ -697,9 +629,9 @@ struct OptDffWorker
new_ff.has_srst = true;
new_ff.sig_srst = srst.first;
new_ff.pol_srst = srst.second;
- if (new_ff.has_en)
+ if (new_ff.has_ce)
new_ff.ce_over_srst = true;
- Cell *new_cell = new_ff.emit(module, NEW_ID);
+ Cell *new_cell = new_ff.emit();
if (new_cell)
dff_cells.push_back(new_cell);
log("Adding SRST signal on %s (%s) from module %s (D = %s, Q = %s, rval = %s).\n",
@@ -712,10 +644,11 @@ struct OptDffWorker
continue;
} else if (GetSize(remaining_indices) != ff.width) {
ff = ff.slice(remaining_indices);
+ ff.cell = cell;
changed = true;
}
}
- if ((!ff.has_srst || !ff.has_en || !ff.ce_over_srst) && !opt.nodffe) {
+ if ((!ff.has_srst || !ff.has_ce || !ff.ce_over_srst) && !opt.nodffe) {
// Try to merge enables.
std::map<std::pair<patterns_t, ctrls_t>, std::vector<int>> groups;
std::vector<int> remaining_indices;
@@ -745,8 +678,8 @@ struct OptDffWorker
if (!opt.simple_dffe)
patterns = find_muxtree_feedback_patterns(ff.sig_d[i], ff.sig_q[i], pattern_t());
if (!patterns.empty() || !enables.empty()) {
- if (ff.has_en)
- enables.insert(ctrl_t(ff.sig_en, ff.pol_en));
+ if (ff.has_ce)
+ enables.insert(ctrl_t(ff.sig_ce, ff.pol_ce));
simplify_patterns(patterns);
groups[std::make_pair(patterns, enables)].push_back(i);
} else
@@ -757,11 +690,11 @@ struct OptDffWorker
FfData new_ff = ff.slice(it.second);
ctrl_t en = make_patterns_logic(it.first.first, it.first.second, ff.is_fine);
- new_ff.has_en = true;
- new_ff.sig_en = en.first;
- new_ff.pol_en = en.second;
+ new_ff.has_ce = true;
+ new_ff.sig_ce = en.first;
+ new_ff.pol_ce = en.second;
new_ff.ce_over_srst = false;
- Cell *new_cell = new_ff.emit(module, NEW_ID);
+ Cell *new_cell = new_ff.emit();
if (new_cell)
dff_cells.push_back(new_cell);
log("Adding EN signal on %s (%s) from module %s (D = %s, Q = %s).\n",
@@ -774,6 +707,7 @@ struct OptDffWorker
continue;
} else if (GetSize(remaining_indices) != ff.width) {
ff = ff.slice(remaining_indices);
+ ff.cell = cell;
changed = true;
}
}
@@ -781,9 +715,116 @@ struct OptDffWorker
if (changed) {
// Rebuild the FF.
- IdString name = cell->name;
- module->remove(cell);
- ff.emit(module, name);
+ ff.emit();
+ did_something = true;
+ }
+ }
+ return did_something;
+ }
+
+ bool run_constbits() {
+ ModWalker modwalker(module->design, module);
+ QuickConeSat qcsat(modwalker);
+
+ // Run as a separate sub-pass, so that we don't mutate (non-FF) cells under ModWalker.
+ bool did_something = false;
+ for (auto cell : module->selected_cells()) {
+ if (!RTLIL::builtin_ff_cell_types().count(cell->type))
+ continue;
+ FfData ff(&initvals, cell);
+
+ // Now check if any bit can be replaced by a constant.
+ pool<int> removed_sigbits;
+ for (int i = 0; i < ff.width; i++) {
+ State val = ff.val_init[i];
+ if (ff.has_arst)
+ val = combine_const(val, ff.val_arst[i]);
+ if (ff.has_srst)
+ val = combine_const(val, ff.val_srst[i]);
+ if (ff.has_sr) {
+ if (ff.sig_clr[i] != (ff.pol_clr ? State::S0 : State::S1))
+ val = combine_const(val, State::S0);
+ if (ff.sig_set[i] != (ff.pol_set ? State::S0 : State::S1))
+ val = combine_const(val, State::S1);
+ }
+ if (val == State::Sm)
+ continue;
+ if (ff.has_clk || ff.has_gclk) {
+ if (!ff.sig_d[i].wire) {
+ val = combine_const(val, ff.sig_d[i].data);
+ if (val == State::Sm)
+ continue;
+ } else {
+ if (!opt.sat)
+ continue;
+ // For each register bit, try to prove that it cannot change from the initial value. If so, remove it
+ if (!modwalker.has_drivers(ff.sig_d.extract(i)))
+ continue;
+ if (val != State::S0 && val != State::S1)
+ continue;
+
+ int init_sat_pi = qcsat.importSigBit(val);
+ int q_sat_pi = qcsat.importSigBit(ff.sig_q[i]);
+ int d_sat_pi = qcsat.importSigBit(ff.sig_d[i]);
+
+ qcsat.prepare();
+
+ // Try to find out whether the register bit can change under some circumstances
+ bool counter_example_found = qcsat.ez->solve(qcsat.ez->IFF(q_sat_pi, init_sat_pi), qcsat.ez->NOT(qcsat.ez->IFF(d_sat_pi, init_sat_pi)));
+
+ // If the register bit cannot change, we can replace it with a constant
+ if (counter_example_found)
+ continue;
+ }
+ }
+ if (ff.has_aload) {
+ if (!ff.sig_ad[i].wire) {
+ val = combine_const(val, ff.sig_ad[i].data);
+ if (val == State::Sm)
+ continue;
+ } else {
+ if (!opt.sat)
+ continue;
+ // For each register bit, try to prove that it cannot change from the initial value. If so, remove it
+ if (!modwalker.has_drivers(ff.sig_ad.extract(i)))
+ continue;
+ if (val != State::S0 && val != State::S1)
+ continue;
+
+ int init_sat_pi = qcsat.importSigBit(val);
+ int q_sat_pi = qcsat.importSigBit(ff.sig_q[i]);
+ int d_sat_pi = qcsat.importSigBit(ff.sig_ad[i]);
+
+ qcsat.prepare();
+
+ // Try to find out whether the register bit can change under some circumstances
+ bool counter_example_found = qcsat.ez->solve(qcsat.ez->IFF(q_sat_pi, init_sat_pi), qcsat.ez->NOT(qcsat.ez->IFF(d_sat_pi, init_sat_pi)));
+
+ // If the register bit cannot change, we can replace it with a constant
+ if (counter_example_found)
+ continue;
+ }
+ }
+ log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", val ? 1 : 0,
+ i, log_id(cell), log_id(cell->type), log_id(module));
+
+ initvals.remove_init(ff.sig_q[i]);
+ module->connect(ff.sig_q[i], val);
+ removed_sigbits.insert(i);
+ }
+ if (!removed_sigbits.empty()) {
+ std::vector<int> keep_bits;
+ for (int i = 0; i < ff.width; i++)
+ if (!removed_sigbits.count(i))
+ keep_bits.push_back(i);
+ if (keep_bits.empty()) {
+ module->remove(cell);
+ did_something = true;
+ continue;
+ }
+ ff = ff.slice(keep_bits);
+ ff.cell = cell;
+ ff.emit();
did_something = true;
}
}
@@ -865,6 +906,8 @@ struct OptDffPass : public Pass {
OptDffWorker worker(opt, mod);
if (worker.run())
did_something = true;
+ if (worker.run_constbits())
+ did_something = true;
}
if (did_something)
diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc
index e36e4419d..be0cd470b 100644
--- a/passes/opt/opt_expr.cc
+++ b/passes/opt/opt_expr.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -393,34 +393,8 @@ int get_highest_hot_index(RTLIL::SigSpec signal)
return -1;
}
-// if the signal has only one bit set, return the index of that bit.
-// otherwise return -1
-int get_onehot_bit_index(RTLIL::SigSpec signal)
-{
- int bit_index = -1;
-
- for (int i = 0; i < GetSize(signal); i++)
- {
- if (signal[i] == RTLIL::State::S0)
- continue;
-
- if (signal[i] != RTLIL::State::S1)
- return -1;
-
- if (bit_index != -1)
- return -1;
-
- bit_index = i;
- }
-
- return bit_index;
-}
-
void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool consume_x, bool mux_undef, bool mux_bool, bool do_fine, bool keepdc, bool noclkinv)
{
- if (!design->selected(module))
- return;
-
CellTypes ct_combinational;
ct_combinational.setup_internals();
ct_combinational.setup_stdcells();
@@ -467,7 +441,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (!noclkinv)
{
- if (cell->type.in(ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce), ID($fsm), ID($memrd), ID($memwr)))
+ if (cell->type.in(ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), ID($aldff), ID($aldffe), ID($sdff), ID($sdffe), ID($sdffce), ID($fsm), ID($memrd), ID($memrd_v2), ID($memwr), ID($memwr_v2)))
handle_polarity_inv(cell, ID::CLK, ID::CLK_POLARITY, assign_map, invert_map);
if (cell->type.in(ID($sr), ID($dffsr), ID($dffsre), ID($dlatchsr))) {
@@ -478,10 +452,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
if (cell->type.in(ID($adff), ID($adffe), ID($adlatch)))
handle_polarity_inv(cell, ID::ARST, ID::ARST_POLARITY, assign_map, invert_map);
+ if (cell->type.in(ID($aldff), ID($aldffe)))
+ handle_polarity_inv(cell, ID::ALOAD, ID::ALOAD_POLARITY, assign_map, invert_map);
+
if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce)))
handle_polarity_inv(cell, ID::SRST, ID::SRST_POLARITY, assign_map, invert_map);
- if (cell->type.in(ID($dffe), ID($adffe), ID($sdffe), ID($sdffce), ID($dffsre), ID($dlatch), ID($adlatch), ID($dlatchsr)))
+ if (cell->type.in(ID($dffe), ID($adffe), ID($aldffe), ID($sdffe), ID($sdffce), ID($dffsre), ID($dlatch), ID($adlatch), ID($dlatchsr)))
handle_polarity_inv(cell, ID::EN, ID::EN_POLARITY, assign_map, invert_map);
handle_clkpol_celltype_swap(cell, "$_SR_N?_", "$_SR_P?_", ID::S, assign_map, invert_map);
@@ -510,6 +487,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
handle_clkpol_celltype_swap(cell, "$_SDFFCE_?N??_", "$_SDFFCE_?P??_", ID::R, assign_map, invert_map);
handle_clkpol_celltype_swap(cell, "$_SDFFCE_???N_", "$_SDFFCE_???P_", ID::E, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_ALDFF_N?_", "$_ALDFF_P?_", ID::C, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_ALDFF_?N_", "$_ALDFF_?P_", ID::L, assign_map, invert_map);
+
+ handle_clkpol_celltype_swap(cell, "$_ALDFFE_N??_", "$_ALDFFE_P??_", ID::C, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_ALDFFE_?N?_", "$_ALDFFE_?P?_", ID::L, assign_map, invert_map);
+ handle_clkpol_celltype_swap(cell, "$_ALDFFE_??N_", "$_ALDFFE_??P_", ID::E, assign_map, invert_map);
+
handle_clkpol_celltype_swap(cell, "$_DFFSR_N??_", "$_DFFSR_P??_", ID::C, assign_map, invert_map);
handle_clkpol_celltype_swap(cell, "$_DFFSR_?N?_", "$_DFFSR_?P?_", ID::S, assign_map, invert_map);
handle_clkpol_celltype_swap(cell, "$_DFFSR_??N_", "$_DFFSR_??P_", ID::R, assign_map, invert_map);
@@ -1526,14 +1510,12 @@ skip_identity:
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y));
- if (sig_b.is_fully_const() && sig_b.size() <= 32)
+ if (sig_b.is_fully_const())
std::swap(sig_a, sig_b), std::swap(a_signed, b_signed), swapped_ab = true;
- if (sig_a.is_fully_def() && sig_a.size() <= 32)
+ if (sig_a.is_fully_def())
{
- int a_val = sig_a.as_int();
-
- if (a_val == 0)
+ if (sig_a.is_fully_zero())
{
cover("opt.opt_expr.mul_shift.zero");
@@ -1547,37 +1529,34 @@ skip_identity:
goto next_cell;
}
- for (int i = 1; i < (a_signed ? sig_a.size()-1 : sig_a.size()); i++)
- if (a_val == (1 << i))
- {
- if (swapped_ab)
- cover("opt.opt_expr.mul_shift.swapped");
- else
- cover("opt.opt_expr.mul_shift.unswapped");
+ int exp;
+ if (sig_a.is_onehot(&exp) && !(a_signed && exp == GetSize(sig_a) - 1))
+ {
+ if (swapped_ab)
+ cover("opt.opt_expr.mul_shift.swapped");
+ else
+ cover("opt.opt_expr.mul_shift.unswapped");
- log_debug("Replacing multiply-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
- a_val, cell->name.c_str(), module->name.c_str(), i);
+ log_debug("Replacing multiply-by-%s cell `%s' in module `%s' with shift-by-%d.\n",
+ log_signal(sig_a), cell->name.c_str(), module->name.c_str(), exp);
- if (!swapped_ab) {
- cell->setPort(ID::A, cell->getPort(ID::B));
- cell->parameters.at(ID::A_WIDTH) = cell->parameters.at(ID::B_WIDTH);
- cell->parameters.at(ID::A_SIGNED) = cell->parameters.at(ID::B_SIGNED);
- }
-
- std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(i, 6);
+ if (!swapped_ab) {
+ cell->setPort(ID::A, cell->getPort(ID::B));
+ cell->parameters.at(ID::A_WIDTH) = cell->parameters.at(ID::B_WIDTH);
+ cell->parameters.at(ID::A_SIGNED) = cell->parameters.at(ID::B_SIGNED);
+ }
- while (GetSize(new_b) > 1 && new_b.back() == RTLIL::State::S0)
- new_b.pop_back();
+ Const new_b = exp;
- cell->type = ID($shl);
- cell->parameters[ID::B_WIDTH] = GetSize(new_b);
- cell->parameters[ID::B_SIGNED] = false;
- cell->setPort(ID::B, new_b);
- cell->check();
+ cell->type = ID($shl);
+ cell->parameters[ID::B_WIDTH] = GetSize(new_b);
+ cell->parameters[ID::B_SIGNED] = false;
+ cell->setPort(ID::B, new_b);
+ cell->check();
- did_something = true;
- goto next_cell;
- }
+ did_something = true;
+ goto next_cell;
+ }
}
sig_a = assign_map(cell->getPort(ID::A));
@@ -1622,7 +1601,7 @@ skip_identity:
}
}
- if (!keepdc && cell->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor)))
+ if (cell->type.in(ID($div), ID($mod), ID($divfloor), ID($modfloor)))
{
bool a_signed = cell->parameters[ID::A_SIGNED].as_bool();
bool b_signed = cell->parameters[ID::B_SIGNED].as_bool();
@@ -1630,11 +1609,9 @@ skip_identity:
SigSpec sig_b = assign_map(cell->getPort(ID::B));
SigSpec sig_y = assign_map(cell->getPort(ID::Y));
- if (sig_b.is_fully_def() && sig_b.size() <= 32)
+ if (sig_b.is_fully_def())
{
- int b_val = sig_b.as_int();
-
- if (b_val == 0)
+ if (sig_b.is_fully_zero())
{
cover("opt.opt_expr.divmod_zero");
@@ -1648,86 +1625,79 @@ skip_identity:
goto next_cell;
}
- for (int i = 1; i < (b_signed ? sig_b.size()-1 : sig_b.size()); i++)
- if (b_val == (1 << i))
+ int exp;
+ if (!keepdc && sig_b.is_onehot(&exp) && !(b_signed && exp == GetSize(sig_b) - 1))
+ {
+ if (cell->type.in(ID($div), ID($divfloor)))
{
- if (cell->type.in(ID($div), ID($divfloor)))
- {
- cover("opt.opt_expr.div_shift");
-
- bool is_truncating = cell->type == ID($div);
- log_debug("Replacing %s-divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n",
- is_truncating ? "truncating" : "flooring",
- b_val, cell->name.c_str(), module->name.c_str(), i);
+ cover("opt.opt_expr.div_shift");
- std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(i, 6);
+ bool is_truncating = cell->type == ID($div);
+ log_debug("Replacing %s-divide-by-%s cell `%s' in module `%s' with shift-by-%d.\n",
+ is_truncating ? "truncating" : "flooring",
+ log_signal(sig_b), cell->name.c_str(), module->name.c_str(), exp);
- while (GetSize(new_b) > 1 && new_b.back() == RTLIL::State::S0)
- new_b.pop_back();
+ Const new_b = exp;
- cell->type = ID($sshr);
- cell->parameters[ID::B_WIDTH] = GetSize(new_b);
- cell->parameters[ID::B_SIGNED] = false;
- cell->setPort(ID::B, new_b);
+ cell->type = ID($sshr);
+ cell->parameters[ID::B_WIDTH] = GetSize(new_b);
+ cell->parameters[ID::B_SIGNED] = false;
+ cell->setPort(ID::B, new_b);
- // Truncating division is the same as flooring division, except when
- // the result is negative and there is a remainder - then trunc = floor + 1
- if (is_truncating && a_signed) {
- Wire *flooring = module->addWire(NEW_ID, sig_y.size());
- cell->setPort(ID::Y, flooring);
-
- Wire *result_neg = module->addWire(NEW_ID);
- module->addXor(NEW_ID, sig_a[sig_a.size()-1], sig_b[sig_b.size()-1], result_neg);
- Wire *rem_nonzero = module->addWire(NEW_ID);
- module->addReduceOr(NEW_ID, sig_a.extract(0, i), rem_nonzero);
- Wire *should_add = module->addWire(NEW_ID);
- module->addAnd(NEW_ID, result_neg, rem_nonzero, should_add);
- module->addAdd(NEW_ID, flooring, should_add, sig_y);
- }
+ // Truncating division is the same as flooring division, except when
+ // the result is negative and there is a remainder - then trunc = floor + 1
+ if (is_truncating && a_signed && GetSize(sig_a) != 0 && exp != 0) {
+ Wire *flooring = module->addWire(NEW_ID, sig_y.size());
+ cell->setPort(ID::Y, flooring);
- cell->check();
+ SigSpec a_sign = sig_a[sig_a.size()-1];
+ SigSpec rem_nonzero = module->ReduceOr(NEW_ID, sig_a.extract(0, exp));
+ SigSpec should_add = module->And(NEW_ID, a_sign, rem_nonzero);
+ module->addAdd(NEW_ID, flooring, should_add, sig_y);
}
- else if (cell->type.in(ID($mod), ID($modfloor)))
+
+ cell->check();
+ }
+ else if (cell->type.in(ID($mod), ID($modfloor)))
+ {
+ cover("opt.opt_expr.mod_mask");
+
+ bool is_truncating = cell->type == ID($mod);
+ log_debug("Replacing %s-modulo-by-%s cell `%s' in module `%s' with bitmask.\n",
+ is_truncating ? "truncating" : "flooring",
+ log_signal(sig_b), cell->name.c_str(), module->name.c_str());
+
+ // truncating modulo has the same masked bits as flooring modulo, but
+ // the sign bits are those of A (except when R=0)
+ if (is_truncating && a_signed && GetSize(sig_a) != 0 && exp != 0)
{
- cover("opt.opt_expr.mod_mask");
+ module->remove(cell);
+ SigSpec truncating = sig_a.extract(0, exp);
- bool is_truncating = cell->type == ID($mod);
- log_debug("Replacing %s-modulo-by-%d cell `%s' in module `%s' with bitmask.\n",
- is_truncating ? "truncating" : "flooring",
- b_val, cell->name.c_str(), module->name.c_str());
+ SigSpec a_sign = sig_a[sig_a.size()-1];
+ SigSpec rem_nonzero = module->ReduceOr(NEW_ID, sig_a.extract(0, exp));
+ SigSpec extend_bit = module->And(NEW_ID, a_sign, rem_nonzero);
- std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(State::S1, i);
+ truncating.append(extend_bit);
+ module->addPos(NEW_ID, truncating, sig_y, true);
+ }
+ else
+ {
+ std::vector<RTLIL::SigBit> new_b = RTLIL::SigSpec(State::S1, exp);
- if (b_signed)
+ if (b_signed || exp == 0)
new_b.push_back(State::S0);
cell->type = ID($and);
cell->parameters[ID::B_WIDTH] = GetSize(new_b);
cell->setPort(ID::B, new_b);
-
- // truncating modulo has the same masked bits as flooring modulo, but
- // the sign bits are those of A (except when R=0)
- if (is_truncating && a_signed) {
- Wire *flooring = module->addWire(NEW_ID, sig_y.size());
- cell->setPort(ID::Y, flooring);
- SigSpec truncating = SigSpec(flooring).extract(0, i);
-
- Wire *rem_nonzero = module->addWire(NEW_ID);
- module->addReduceOr(NEW_ID, truncating, rem_nonzero);
- SigSpec a_sign = sig_a[sig_a.size()-1];
- Wire *extend_bit = module->addWire(NEW_ID);
- module->addAnd(NEW_ID, a_sign, rem_nonzero, extend_bit);
-
- truncating.append(extend_bit);
- module->addPos(NEW_ID, truncating, sig_y, true);
- }
-
cell->check();
}
-
- did_something = true;
- goto next_cell;
}
+
+ did_something = true;
+ goto next_cell;
+ }
}
}
@@ -1957,8 +1927,8 @@ skip_alu_split:
replace = true;
}
- int const_bit_hot = get_onehot_bit_index(const_sig);
- if (const_bit_hot >= 0 && const_bit_hot < var_width)
+ int const_bit_hot;
+ if (const_sig.is_onehot(&const_bit_hot) && const_bit_hot < var_width)
{
RTLIL::SigSpec var_high_sig(RTLIL::State::S0, var_width - const_bit_hot);
for (int i = const_bit_hot; i < var_width; i++) {
@@ -2044,6 +2014,23 @@ skip_alu_split:
}
}
+void replace_const_connections(RTLIL::Module *module) {
+ SigMap assign_map(module);
+ for (auto cell : module->selected_cells())
+ {
+ std::vector<std::pair<RTLIL::IdString, SigSpec>> changes;
+ for (auto &conn : cell->connections()) {
+ SigSpec mapped = assign_map(conn.second);
+ if (conn.second != mapped && mapped.is_fully_const())
+ changes.push_back({conn.first, mapped});
+ }
+ if (!changes.empty())
+ did_something = true;
+ for (auto &it : changes)
+ cell->setPort(it.first, it.second);
+ }
+}
+
struct OptExprPass : public Pass {
OptExprPass() : Pass("opt_expr", "perform const folding and simple expression rewriting") { }
void help() override
@@ -2154,6 +2141,11 @@ struct OptExprPass : public Pass {
design->scratchpad_set_bool("opt.did_something", true);
} while (did_something);
+ did_something = false;
+ replace_const_connections(module);
+ if (did_something)
+ design->scratchpad_set_bool("opt.did_something", true);
+
log_suppressed();
}
diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc
index 623101016..3b079d964 100644
--- a/passes/opt/opt_lut.cc
+++ b/passes/opt/opt_lut.cc
@@ -24,16 +24,22 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
+struct dlogic_t {
+ IdString cell_type;
+ // LUT input idx -> hard cell's port name
+ dict<int, IdString> lut_input_port;
+};
+
struct OptLutWorker
{
- dict<IdString, dict<int, IdString>> &dlogic;
+ const std::vector<dlogic_t> &dlogic;
RTLIL::Module *module;
ModIndex index;
SigMap sigmap;
pool<RTLIL::Cell*> luts;
dict<RTLIL::Cell*, int> luts_arity;
- dict<RTLIL::Cell*, pool<RTLIL::Cell*>> luts_dlogics;
+ dict<RTLIL::Cell*, pool<std::pair<int, RTLIL::Cell*>>> luts_dlogics;
dict<RTLIL::Cell*, pool<int>> luts_dlogic_inputs;
int eliminated_count = 0, combined_count = 0;
@@ -64,7 +70,7 @@ struct OptLutWorker
void show_stats_by_arity()
{
dict<int, int> arity_counts;
- dict<IdString, int> dlogic_counts;
+ std::vector<int> dlogic_counts(dlogic.size());
int max_arity = 0;
for (auto lut_arity : luts_arity)
@@ -77,7 +83,7 @@ struct OptLutWorker
{
for (auto &lut_dlogic : lut_dlogics.second)
{
- dlogic_counts[lut_dlogic->type]++;
+ dlogic_counts[lut_dlogic.first]++;
}
}
@@ -87,13 +93,13 @@ struct OptLutWorker
if (arity_counts[arity])
log(" %d-LUT %16d\n", arity, arity_counts[arity]);
}
- for (auto &dlogic_count : dlogic_counts)
+ for (int i = 0; i < GetSize(dlogic); i++)
{
- log(" with %-12s %4d\n", dlogic_count.first.c_str(), dlogic_count.second);
+ log(" with %-12s (#%d) %4d\n", dlogic[i].cell_type.c_str(), i, dlogic_counts[i]);
}
}
- OptLutWorker(dict<IdString, dict<int, IdString>> &dlogic, RTLIL::Module *module, int limit) :
+ OptLutWorker(const std::vector<dlogic_t> &dlogic, RTLIL::Module *module, int limit) :
dlogic(dlogic), module(module), index(module), sigmap(module)
{
log("Discovering LUTs.\n");
@@ -116,20 +122,19 @@ struct OptLutWorker
// First, find all dedicated logic we're connected to. This results in an overapproximation
// of such connections.
- pool<RTLIL::Cell*> lut_all_dlogics;
+ pool<std::pair<int, RTLIL::Cell*>> lut_all_dlogics;
for (int i = 0; i < lut_width; i++)
{
SigBit bit = lut_input[i];
for (auto &port : index.query_ports(bit))
{
- if (dlogic.count(port.cell->type))
+ for (int j = 0; j < GetSize(dlogic); j++)
{
- auto &dlogic_map = dlogic[port.cell->type];
- if (dlogic_map.count(i))
+ if (dlogic[j].cell_type == port.cell->type)
{
- if (port.port == dlogic_map[i])
+ if (port.port == dlogic[j].lut_input_port.at(i, IdString()))
{
- lut_all_dlogics.insert(port.cell);
+ lut_all_dlogics.insert({j, port.cell});
}
}
}
@@ -143,25 +148,25 @@ struct OptLutWorker
// * The connection is illegal.
// In either of these cases, we don't need to concern ourselves with preserving the connection
// between this LUT and this dedicated logic cell.
- pool<RTLIL::Cell*> lut_legal_dlogics;
+ pool<std::pair<int, RTLIL::Cell*>> lut_legal_dlogics;
pool<int> lut_dlogic_inputs;
for (auto lut_dlogic : lut_all_dlogics)
{
- auto &dlogic_map = dlogic[lut_dlogic->type];
+ auto &dlogic_map = dlogic[lut_dlogic.first].lut_input_port;
bool legal = true;
for (auto &dlogic_conn : dlogic_map)
{
if (lut_width <= dlogic_conn.first)
{
- log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
+ log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type.c_str(), log_id(module), log_id(lut_dlogic.second));
log_debug(" LUT input A[%d] not present.\n", dlogic_conn.first);
legal = false;
break;
}
- if (sigmap(lut_input[dlogic_conn.first]) != sigmap(lut_dlogic->getPort(dlogic_conn.second)))
+ if (sigmap(lut_input[dlogic_conn.first]) != sigmap(lut_dlogic.second->getPort(dlogic_conn.second)))
{
- log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
- log_debug(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic->getPort(dlogic_conn.second)));
+ log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type.c_str(), log_id(module), log_id(lut_dlogic.second));
+ log_debug(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic.second->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic.second->getPort(dlogic_conn.second)));
legal = false;
break;
}
@@ -169,7 +174,7 @@ struct OptLutWorker
if (legal)
{
- log_debug(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
+ log_debug(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic.second->type.c_str(), log_id(module), log_id(lut_dlogic.second));
lut_legal_dlogics.insert(lut_dlogic);
for (auto &dlogic_conn : dlogic_map)
lut_dlogic_inputs.insert(dlogic_conn.first);
@@ -544,7 +549,7 @@ struct OptLutPass : public Pass {
{
log_header(design, "Executing OPT_LUT pass (optimize LUTs).\n");
- dict<IdString, dict<int, IdString>> dlogic;
+ std::vector<dlogic_t> dlogic;
int limit = -1;
size_t argidx;
@@ -556,7 +561,8 @@ struct OptLutPass : public Pass {
split(tokens, args[++argidx], ':');
if (tokens.size() < 2)
log_cmd_error("The -dlogic option requires at least one connection.\n");
- IdString type = "\\" + tokens[0];
+ dlogic_t entry;
+ entry.cell_type = "\\" + tokens[0];
for (auto it = tokens.begin() + 1; it != tokens.end(); ++it) {
std::vector<std::string> conn_tokens;
split(conn_tokens, *it, '=');
@@ -564,8 +570,9 @@ struct OptLutPass : public Pass {
log_cmd_error("Invalid format of -dlogic signal mapping.\n");
IdString logic_port = "\\" + conn_tokens[0];
int lut_input = atoi(conn_tokens[1].c_str());
- dlogic[type][lut_input] = logic_port;
+ entry.lut_input_port[lut_input] = logic_port;
}
+ dlogic.push_back(entry);
continue;
}
if (args[argidx] == "-limit" && argidx + 1 < args.size())
diff --git a/passes/opt/opt_lut_ins.cc b/passes/opt/opt_lut_ins.cc
index bb40e1e55..2f7c392b2 100644
--- a/passes/opt/opt_lut_ins.cc
+++ b/passes/opt/opt_lut_ins.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -193,6 +193,12 @@ struct OptLutInsPass : public Pass {
swz += extra;
}
}
+ if (techname == "gowin") {
+ // Pad the LUT to 1 input, adding consts from the front.
+ if (new_inputs.empty()) {
+ new_inputs.insert(new_inputs.begin(), State::S0);
+ }
+ }
Const new_lut(0, 1 << GetSize(new_inputs));
for (int i = 0; i < GetSize(new_lut); i++) {
int lidx = 0;
@@ -209,9 +215,9 @@ struct OptLutInsPass : public Pass {
}
new_lut[i] = lut[lidx];
}
- // For ecp5, do not replace with a const driver — the nextpnr
+ // For ecp5, and gowin do not replace with a const driver — the nextpnr
// packer requires a complete set of LUTs for wide LUT muxes.
- if (new_inputs.empty() && techname != "ecp5") {
+ if (new_inputs.empty() && techname != "ecp5" && techname != "gowin") {
// const driver.
remove_cells.push_back(cell);
module->connect(output, new_lut[0]);
diff --git a/passes/opt/opt_mem.cc b/passes/opt/opt_mem.cc
index 49a0ac51a..edadf2c7b 100644
--- a/passes/opt/opt_mem.cc
+++ b/passes/opt/opt_mem.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -51,8 +51,32 @@ struct OptMemPass : public Pass {
int total_count = 0;
for (auto module : design->selected_modules()) {
+ SigMap sigmap(module);
+ FfInitVals initvals(&sigmap, module);
for (auto &mem : Mem::get_selected_memories(module)) {
+ bool changed = false;
+ for (auto &port : mem.wr_ports) {
+ if (port.en.is_fully_zero()) {
+ port.removed = true;
+ changed = true;
+ total_count++;
+ }
+ }
+ if (changed) {
+ mem.emit();
+ }
+
if (mem.wr_ports.empty() && mem.inits.empty()) {
+ // The whole memory array will contain
+ // only State::Sx, but the embedded read
+ // registers could have reset or init values.
+ // They will probably be optimized away by
+ // opt_dff later.
+ for (int i = 0; i < GetSize(mem.rd_ports); i++) {
+ mem.extract_rdff(i, &initvals);
+ auto &port = mem.rd_ports[i];
+ module->connect(port.data, Const(State::Sx, GetSize(port.data)));
+ }
mem.remove();
total_count++;
}
diff --git a/passes/opt/opt_mem_feedback.cc b/passes/opt/opt_mem_feedback.cc
new file mode 100644
index 000000000..20a2a79ed
--- /dev/null
+++ b/passes/opt/opt_mem_feedback.cc
@@ -0,0 +1,350 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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 "kernel/yosys.h"
+#include "kernel/sigtools.h"
+#include "kernel/mem.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+// Describes found feedback path.
+struct FeedbackPath {
+ // Which write port it is.
+ int wrport_idx;
+ // Which data bit of that write port it is.
+ int data_bit_idx;
+ // Values of all mux select signals that need to be set to select this path.
+ dict<RTLIL::SigBit, bool> condition;
+ // The exact feedback bit used (used to match read port).
+ SigBit feedback_bit;
+
+ FeedbackPath(int wrport_idx, int data_bit_idx, dict<RTLIL::SigBit, bool> condition, SigBit feedback_bit) : wrport_idx(wrport_idx), data_bit_idx(data_bit_idx), condition(condition), feedback_bit(feedback_bit) {}
+};
+
+struct OptMemFeedbackWorker
+{
+ RTLIL::Design *design;
+ RTLIL::Module *module;
+ SigMap sigmap, sigmap_xmux;
+ FfInitVals initvals;
+
+ dict<RTLIL::SigBit, std::pair<RTLIL::Cell*, int>> sig_to_mux;
+ dict<RTLIL::SigBit, int> sig_users_count;
+ dict<pair<pool<dict<SigBit, bool>>, SigBit>, SigBit> conditions_logic_cache;
+
+
+ // -----------------------------------------------------------------
+ // Converting feedbacks to async read ports to proper enable signals
+ // -----------------------------------------------------------------
+
+ void find_data_feedback(const pool<RTLIL::SigBit> &async_rd_bits, RTLIL::SigBit sig,
+ const dict<RTLIL::SigBit, bool> &state,
+ int wrport_idx, int data_bit_idx,
+ std::vector<FeedbackPath> &paths)
+ {
+ if (async_rd_bits.count(sig)) {
+ paths.push_back(FeedbackPath(wrport_idx, data_bit_idx, state, sig));
+ return;
+ }
+
+ if (sig_users_count[sig] != 1) {
+ // Only descend into muxes if we're the only user.
+ return;
+ }
+
+ if (sig_to_mux.count(sig) == 0)
+ return;
+
+ RTLIL::Cell *cell = sig_to_mux.at(sig).first;
+ int bit_idx = sig_to_mux.at(sig).second;
+
+ std::vector<RTLIL::SigBit> sig_a = sigmap(cell->getPort(ID::A));
+ std::vector<RTLIL::SigBit> sig_b = sigmap(cell->getPort(ID::B));
+ std::vector<RTLIL::SigBit> sig_s = sigmap(cell->getPort(ID::S));
+ std::vector<RTLIL::SigBit> sig_y = sigmap(cell->getPort(ID::Y));
+ log_assert(sig_y.at(bit_idx) == sig);
+
+ for (int i = 0; i < GetSize(sig_s); i++)
+ if (state.count(sig_s[i]) && state.at(sig_s[i]) == true) {
+ find_data_feedback(async_rd_bits, sig_b.at(bit_idx + i*sig_y.size()), state, wrport_idx, data_bit_idx, paths);
+ return;
+ }
+
+
+ for (int i = 0; i < GetSize(sig_s); i++)
+ {
+ if (state.count(sig_s[i]) && state.at(sig_s[i]) == false)
+ continue;
+
+ dict<RTLIL::SigBit, bool> new_state = state;
+ new_state[sig_s[i]] = true;
+
+ find_data_feedback(async_rd_bits, sig_b.at(bit_idx + i*sig_y.size()), new_state, wrport_idx, data_bit_idx, paths);
+ }
+
+ dict<RTLIL::SigBit, bool> new_state = state;
+ for (auto bit : sig_s)
+ new_state[bit] = false;
+
+ find_data_feedback(async_rd_bits, sig_a.at(bit_idx), new_state, wrport_idx, data_bit_idx, paths);
+ }
+
+ RTLIL::SigBit conditions_to_logic(pool<dict<RTLIL::SigBit, bool>> &conditions, SigBit olden)
+ {
+ auto key = make_pair(conditions, olden);
+
+ if (conditions_logic_cache.count(key))
+ return conditions_logic_cache.at(key);
+
+ RTLIL::SigSpec terms;
+ for (auto &cond : conditions) {
+ RTLIL::SigSpec sig1, sig2;
+ for (auto &it : cond) {
+ sig1.append(it.first);
+ sig2.append(it.second ? RTLIL::State::S1 : RTLIL::State::S0);
+ }
+ terms.append(module->Ne(NEW_ID, sig1, sig2));
+ }
+
+ if (olden != State::S1)
+ terms.append(olden);
+
+ if (GetSize(terms) == 0)
+ terms = State::S1;
+
+ if (GetSize(terms) > 1)
+ terms = module->ReduceAnd(NEW_ID, terms);
+
+ return conditions_logic_cache[key] = terms;
+ }
+
+ void translate_rd_feedback_to_en(Mem &mem)
+ {
+ // Look for async read ports that may be suitable for feedback paths.
+ dict<RTLIL::SigSpec, std::vector<pool<RTLIL::SigBit>>> async_rd_bits;
+
+ for (auto &port : mem.rd_ports)
+ {
+ if (port.clk_enable)
+ continue;
+
+ for (int sub = 0; sub < (1 << port.wide_log2); sub++) {
+ SigSpec addr = sigmap_xmux(port.sub_addr(sub));
+ async_rd_bits[addr].resize(mem.width);
+ for (int i = 0; i < mem.width; i++)
+ async_rd_bits[addr][i].insert(sigmap(port.data[i + sub * mem.width]));
+ }
+ }
+
+ if (async_rd_bits.empty())
+ return;
+
+ // Look for actual feedback paths.
+ std::vector<FeedbackPath> paths;
+
+ for (int i = 0; i < GetSize(mem.wr_ports); i++)
+ {
+ auto &port = mem.wr_ports[i];
+
+ log(" Analyzing %s.%s write port %d.\n", log_id(module), log_id(mem.memid), i);
+
+ for (int sub = 0; sub < (1 << port.wide_log2); sub++)
+ {
+ SigSpec addr = sigmap_xmux(port.sub_addr(sub));
+
+ if (!async_rd_bits.count(addr))
+ continue;
+
+ for (int j = 0; j < mem.width; j++)
+ {
+ int bit_idx = sub * mem.width + j;
+
+ if (port.en[bit_idx] == State::S0)
+ continue;
+
+ dict<RTLIL::SigBit, bool> state;
+
+ find_data_feedback(async_rd_bits.at(addr).at(j), sigmap(port.data[bit_idx]), state, i, bit_idx, paths);
+ }
+ }
+ }
+
+ if (paths.empty())
+ return;
+
+ // Now determine which read ports are actually used only for
+ // feedback paths, and can be removed.
+
+ dict<SigBit, int> feedback_users_count;
+ for (auto &path : paths)
+ feedback_users_count[path.feedback_bit]++;
+
+ pool<SigBit> feedback_ok;
+ for (auto &port : mem.rd_ports)
+ {
+ if (port.clk_enable)
+ continue;
+
+ bool ok = true;
+ for (auto bit : sigmap(port.data))
+ if (sig_users_count[bit] != feedback_users_count[bit])
+ ok = false;
+
+ if (ok)
+ {
+ // This port is going bye-bye.
+ for (auto bit : sigmap(port.data))
+ feedback_ok.insert(bit);
+
+ port.removed = true;
+ }
+ }
+
+ if (feedback_ok.empty())
+ return;
+
+ // Prepare a feedback condition list grouped by port bits.
+
+ dict<std::pair<int, int>, pool<dict<SigBit, bool>>> portbit_conds;
+ for (auto &path : paths)
+ if (feedback_ok.count(path.feedback_bit))
+ portbit_conds[std::make_pair(path.wrport_idx, path.data_bit_idx)].insert(path.condition);
+
+ if (portbit_conds.empty())
+ return;
+
+ // Okay, let's do it.
+
+ log("Populating enable bits on write ports of memory %s.%s with async read feedback:\n", log_id(module), log_id(mem.memid));
+
+ // If a write port has a feedback path that we're about to bypass,
+ // but also has priority over some other write port, the feedback
+ // path is not necessarily a NOP — it may overwrite the other port.
+ // Emulate this effect by converting the priority to soft logic
+ // (this will affect the other port's enable signal).
+ for (auto &it : portbit_conds)
+ {
+ int wrport_idx = it.first.first;
+ auto &port = mem.wr_ports[wrport_idx];
+
+ for (int i = 0; i < wrport_idx; i++)
+ if (port.priority_mask[i])
+ mem.emulate_priority(i, wrport_idx, &initvals);
+ }
+
+ for (auto &it : portbit_conds)
+ {
+ int wrport_idx = it.first.first;
+ int bit = it.first.second;
+ auto &port = mem.wr_ports[wrport_idx];
+
+ port.en[bit] = conditions_to_logic(it.second, port.en[bit]);
+ log(" Port %d bit %d: added enable logic for %d different cases.\n", wrport_idx, bit, GetSize(it.second));
+ }
+
+ mem.emit();
+
+ for (auto bit : feedback_ok)
+ module->connect(bit, State::Sx);
+
+ design->scratchpad_set_bool("opt.did_something", true);
+ }
+
+ // -------------
+ // Setup and run
+ // -------------
+
+ OptMemFeedbackWorker(RTLIL::Design *design) : design(design) {}
+
+ void operator()(RTLIL::Module* module)
+ {
+ std::vector<Mem> memories = Mem::get_selected_memories(module);
+
+ this->module = module;
+ sigmap.set(module);
+ initvals.set(&sigmap, module);
+ sig_to_mux.clear();
+ conditions_logic_cache.clear();
+
+ sigmap_xmux = sigmap;
+
+ for (auto wire : module->wires()) {
+ if (wire->port_output)
+ for (auto bit : sigmap(wire))
+ sig_users_count[bit]++;
+ }
+
+ for (auto cell : module->cells())
+ {
+ if (cell->type == ID($mux))
+ {
+ RTLIL::SigSpec sig_a = sigmap_xmux(cell->getPort(ID::A));
+ RTLIL::SigSpec sig_b = sigmap_xmux(cell->getPort(ID::B));
+
+ if (sig_a.is_fully_undef())
+ sigmap_xmux.add(cell->getPort(ID::Y), sig_b);
+ else if (sig_b.is_fully_undef())
+ sigmap_xmux.add(cell->getPort(ID::Y), sig_a);
+ }
+
+ if (cell->type.in(ID($mux), ID($pmux)))
+ {
+ std::vector<RTLIL::SigBit> sig_y = sigmap(cell->getPort(ID::Y));
+ for (int i = 0; i < int(sig_y.size()); i++)
+ sig_to_mux[sig_y[i]] = std::pair<RTLIL::Cell*, int>(cell, i);
+ }
+
+ for (auto &conn : cell->connections())
+ if (!cell->known() || cell->input(conn.first))
+ for (auto bit : sigmap(conn.second))
+ sig_users_count[bit]++;
+ }
+
+ for (auto &mem : memories)
+ translate_rd_feedback_to_en(mem);
+ }
+};
+
+struct OptMemFeedbackPass : public Pass {
+ OptMemFeedbackPass() : Pass("opt_mem_feedback", "convert memory read-to-write port feedback paths to write enables") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" opt_mem_feedback [selection]\n");
+ log("\n");
+ log("This pass detects cases where an asynchronous read port is only connected via\n");
+ log("a mux tree to a write port with the same address. When such a connection is\n");
+ log("found, it is replaced with a new condition on an enable signal, allowing\n");
+ log("for removal of the read port.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override {
+ log_header(design, "Executing OPT_MEM_FEEDBACK pass (finding memory read-to-write feedback paths).\n");
+ extra_args(args, 1, design);
+ OptMemFeedbackWorker worker(design);
+
+ for (auto module : design->selected_modules())
+ worker(module);
+ }
+} OptMemFeedbackPass;
+
+PRIVATE_NAMESPACE_END
+
diff --git a/passes/opt/opt_mem_priority.cc b/passes/opt/opt_mem_priority.cc
new file mode 100644
index 000000000..a9b145bea
--- /dev/null
+++ b/passes/opt/opt_mem_priority.cc
@@ -0,0 +1,109 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * 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/modtools.h"
+#include "kernel/qcsat.h"
+#include "kernel/mem.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct OptMemPriorityPass : public Pass {
+ OptMemPriorityPass() : Pass("opt_mem_priority", "remove priority relations between write ports that can never collide") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" opt_mem_priority [selection]\n");
+ log("\n");
+ log("This pass detects cases where one memory write port has priority over another\n");
+ log("even though they can never collide with each other -- ie. there can never be\n");
+ log("a situation where a given memory bit is written by both ports at the same\n");
+ log("time, for example because of always-different addresses, or mutually exclusive\n");
+ log("enable signals. In such cases, the priority relation is removed.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override {
+ log_header(design, "Executing OPT_MEM_PRIORITY pass (removing unnecessary memory write priority relations).\n");
+ extra_args(args, 1, design);
+
+ ModWalker modwalker(design);
+
+ int total_count = 0;
+ for (auto module : design->selected_modules()) {
+ modwalker.setup(module);
+ for (auto &mem : Mem::get_selected_memories(module)) {
+ bool mem_changed = false;
+ QuickConeSat qcsat(modwalker);
+ for (int i = 0; i < GetSize(mem.wr_ports); i++) {
+ auto &wport1 = mem.wr_ports[i];
+ for (int j = 0; j < GetSize(mem.wr_ports); j++) {
+ auto &wport2 = mem.wr_ports[j];
+ if (!wport1.priority_mask[j])
+ continue;
+ // No mixed width support — we could do it, but
+ // that would complicate code and wouldn't help
+ // anything since we run this pass before
+ // wide ports are created in normal flow.
+ if (wport1.wide_log2 != wport2.wide_log2)
+ continue;
+ // Two ports with priority, let's go.
+ pool<std::pair<SigBit, SigBit>> checked;
+ SigSpec addr1 = wport1.addr;
+ SigSpec addr2 = wport2.addr;
+ int abits = std::max(GetSize(addr1), GetSize(addr2));
+ addr1.extend_u0(abits);
+ addr2.extend_u0(abits);
+ int addr_eq = qcsat.ez->vec_eq(qcsat.importSig(addr1), qcsat.importSig(addr2));
+ bool ok = true;
+ for (int k = 0; k < GetSize(wport1.data); k++) {
+ SigBit wen1 = wport1.en[k];
+ SigBit wen2 = wport2.en[k];
+ if (checked.count({wen1, wen2}))
+ continue;
+ int wen1_sat = qcsat.importSigBit(wen1);
+ int wen2_sat = qcsat.importSigBit(wen2);
+ qcsat.prepare();
+ if (qcsat.ez->solve(wen1_sat, wen2_sat, addr_eq)) {
+ ok = false;
+ break;
+ }
+ checked.insert({wen1, wen2});
+ }
+ if (ok) {
+ total_count++;
+ mem_changed = true;
+ wport1.priority_mask[j] = false;
+ }
+ }
+ }
+ if (mem_changed)
+ mem.emit();
+ }
+ }
+
+ if (total_count)
+ design->scratchpad_set_bool("opt.did_something", true);
+ log("Performed a total of %d transformations.\n", total_count);
+ }
+} OptMemPriorityPass;
+
+PRIVATE_NAMESPACE_END
+
diff --git a/passes/opt/opt_mem_widen.cc b/passes/opt/opt_mem_widen.cc
new file mode 100644
index 000000000..95e01088c
--- /dev/null
+++ b/passes/opt/opt_mem_widen.cc
@@ -0,0 +1,107 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * 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/mem.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct OptMemWidenPass : public Pass {
+ OptMemWidenPass() : Pass("opt_mem_widen", "optimize memories where all ports are wide") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" opt_mem_widen [options] [selection]\n");
+ log("\n");
+ log("This pass looks for memories where all ports are wide and adjusts the base\n");
+ log("memory width up until that stops being the case.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing OPT_MEM_WIDEN pass (optimize memories where all ports are wide).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ // if (args[argidx] == "-nomux") {
+ // mode_nomux = true;
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ int total_count = 0;
+ for (auto module : design->selected_modules()) {
+ for (auto &mem : Mem::get_selected_memories(module)) {
+ // If the memory has no read ports, opt_clean will remove it
+ // instead.
+ if (mem.rd_ports.empty())
+ continue;
+ int factor_log2 = mem.rd_ports[0].wide_log2;
+ for (auto &port : mem.rd_ports)
+ if (port.wide_log2 < factor_log2)
+ factor_log2 = port.wide_log2;
+ for (auto &port : mem.wr_ports)
+ if (port.wide_log2 < factor_log2)
+ factor_log2 = port.wide_log2;
+ if (factor_log2 == 0)
+ continue;
+ log("Widening base width of memory %s in module %s by factor %d.\n", log_id(mem.memid), log_id(module->name), 1 << factor_log2);
+ total_count++;
+ // The inits are too messy to expand one-by-one, for they may
+ // collide with one another after expansion. Just hit it with
+ // a hammer.
+ bool has_init = !mem.inits.empty();
+ Const init_data;
+ if (has_init) {
+ init_data = mem.get_init_data();
+ mem.clear_inits();
+ }
+ mem.width <<= factor_log2;
+ mem.size >>= factor_log2;
+ mem.start_offset >>= factor_log2;
+ if (has_init) {
+ MemInit new_init;
+ new_init.addr = mem.start_offset;
+ new_init.data = init_data;
+ new_init.en = Const(State::S1, mem.width);
+ mem.inits.push_back(new_init);
+ }
+ for (auto &port : mem.rd_ports) {
+ port.wide_log2 -= factor_log2;
+ port.addr = port.addr.extract_end(factor_log2);
+ }
+ for (auto &port : mem.wr_ports) {
+ port.wide_log2 -= factor_log2;
+ port.addr = port.addr.extract_end(factor_log2);
+ }
+ mem.emit();
+ }
+ }
+
+ if (total_count)
+ design->scratchpad_set_bool("opt.did_something", true);
+ log("Performed a total of %d transformations.\n", total_count);
+ }
+} OptMemWidenPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc
index 9086943dc..115eb97a9 100644
--- a/passes/opt/opt_merge.cc
+++ b/passes/opt/opt_merge.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -18,6 +18,7 @@
*/
#include "kernel/register.h"
+#include "kernel/ffinit.h"
#include "kernel/sigtools.h"
#include "kernel/log.h"
#include "kernel/celltypes.h"
@@ -35,7 +36,7 @@ struct OptMergeWorker
RTLIL::Design *design;
RTLIL::Module *module;
SigMap assign_map;
- SigMap dff_init_map;
+ FfInitVals initvals;
bool mode_share_all;
CellTypes ct;
@@ -121,8 +122,7 @@ struct OptMergeWorker
if (it.first == ID::Q && RTLIL::builtin_ff_cell_types().count(cell->type)) {
// For the 'Q' output of state elements,
// use its (* init *) attribute value
- for (const auto &b : dff_init_map(it.second))
- sig.append(b.wire ? State::Sx : b);
+ sig = initvals(it.second);
}
else
continue;
@@ -176,12 +176,8 @@ struct OptMergeWorker
if (it.first == ID::Q && RTLIL::builtin_ff_cell_types().count(cell1->type)) {
// For the 'Q' output of state elements,
// use the (* init *) attribute value
- auto &sig1 = conn1[it.first];
- for (const auto &b : dff_init_map(it.second))
- sig1.append(b.wire ? State::Sx : b);
- auto &sig2 = conn2[it.first];
- for (const auto &b : dff_init_map(cell2->getPort(it.first)))
- sig2.append(b.wire ? State::Sx : b);
+ conn1[it.first] = initvals(it.second);
+ conn2[it.first] = initvals(cell2->getPort(it.first));
}
else {
conn1[it.first] = RTLIL::SigSpec();
@@ -247,14 +243,7 @@ struct OptMergeWorker
log("Finding identical cells in module `%s'.\n", module->name.c_str());
assign_map.set(module);
- dff_init_map.set(module);
- for (auto &it : module->wires_)
- if (it.second->attributes.count(ID::init) != 0) {
- Const initval = it.second->attributes.at(ID::init);
- for (int i = 0; i < GetSize(initval) && i < GetSize(it.second); i++)
- if (initval[i] == State::S0 || initval[i] == State::S1)
- dff_init_map.add(SigBit(it.second, i), initval[i]);
- }
+ initvals.set(&assign_map, module);
bool did_something = true;
while (did_something)
@@ -293,19 +282,12 @@ struct OptMergeWorker
RTLIL::SigSpec other_sig = r.first->second->getPort(it.first);
log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(),
log_signal(it.second), log_signal(other_sig));
+ Const init = initvals(other_sig);
+ initvals.remove_init(it.second);
+ initvals.remove_init(other_sig);
module->connect(RTLIL::SigSig(it.second, other_sig));
assign_map.add(it.second, other_sig);
-
- if (it.first == ID::Q && RTLIL::builtin_ff_cell_types().count(cell->type)) {
- for (auto c : it.second.chunks()) {
- auto jt = c.wire->attributes.find(ID::init);
- if (jt == c.wire->attributes.end())
- continue;
- for (int i = c.offset; i < c.offset + c.width; i++)
- jt->second[i] = State::Sx;
- }
- dff_init_map.add(it.second, Const(State::Sx, GetSize(it.second)));
- }
+ initvals.set_init(other_sig, init);
}
}
log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str());
diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc
index 67b283e11..100b1b495 100644
--- a/passes/opt/opt_muxtree.cc
+++ b/passes/opt/opt_muxtree.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -372,29 +372,28 @@ struct OptMuxtreeWorker
int port_idx = 0, port_off = 0;
vector<int> bits = sig2bits(sig, false);
for (int i = 0; i < GetSize(bits); i++) {
- if (bits[i] < 0)
- continue;
- if (knowledge.known_inactive.at(bits[i])) {
- sig[i] = State::S0;
- did_something = true;
- } else
- if (knowledge.known_active.at(bits[i])) {
- sig[i] = State::S1;
- did_something = true;
- }
- if (width) {
- if (ctrl_bits.count(bits[i])) {
- sig[i] = ctrl_bits.at(bits[i]) == port_idx ? State::S1 : State::S0;
+ if (bits[i] >= 0) {
+ if (knowledge.known_inactive.at(bits[i])) {
+ sig[i] = State::S0;
+ did_something = true;
+ } else
+ if (knowledge.known_active.at(bits[i])) {
+ sig[i] = State::S1;
did_something = true;
}
- if (++port_off == width)
- port_idx++, port_off=0;
- } else {
if (ctrl_bits.count(bits[i])) {
- sig[i] = State::S0;
+ if (width) {
+ sig[i] = ctrl_bits.at(bits[i]) == port_idx ? State::S1 : State::S0;
+ } else {
+ sig[i] = State::S0;
+ }
did_something = true;
}
}
+ if (width) {
+ if (++port_off == width)
+ port_idx++, port_off=0;
+ }
}
if (did_something) {
diff --git a/passes/opt/opt_reduce.cc b/passes/opt/opt_reduce.cc
index 28de9ceb6..1a7c93fbd 100644
--- a/passes/opt/opt_reduce.cc
+++ b/passes/opt/opt_reduce.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -100,7 +100,7 @@ struct OptReduceWorker
return;
}
- void opt_mux(RTLIL::Cell *cell)
+ void opt_pmux(RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B));
@@ -141,20 +141,20 @@ struct OptReduceWorker
handled_sig.insert(this_b);
}
- if (new_sig_s.size() != sig_s.size()) {
- log(" New ctrl vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_s));
- did_something = true;
- total_count++;
- }
-
if (new_sig_s.size() == 0)
{
- module->connect(RTLIL::SigSig(cell->getPort(ID::Y), cell->getPort(ID::A)));
+ module->connect(cell->getPort(ID::Y), cell->getPort(ID::A));
assign_map.add(cell->getPort(ID::Y), cell->getPort(ID::A));
module->remove(cell);
+ did_something = true;
+ total_count++;
+ return;
}
- else
- {
+
+ if (new_sig_s.size() != sig_s.size() || (new_sig_s.size() == 1 && cell->type == ID($pmux))) {
+ log(" New ctrl vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_s));
+ did_something = true;
+ total_count++;
cell->setPort(ID::B, new_sig_b);
cell->setPort(ID::S, new_sig_s);
if (new_sig_s.size() > 1) {
@@ -166,81 +166,347 @@ struct OptReduceWorker
}
}
- void opt_mux_bits(RTLIL::Cell *cell)
+ void opt_bmux(RTLIL::Cell *cell)
{
- std::vector<RTLIL::SigBit> sig_a = assign_map(cell->getPort(ID::A)).to_sigbit_vector();
- std::vector<RTLIL::SigBit> sig_b = assign_map(cell->getPort(ID::B)).to_sigbit_vector();
- std::vector<RTLIL::SigBit> sig_y = assign_map(cell->getPort(ID::Y)).to_sigbit_vector();
+ RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A));
+ RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID::S));
+ int width = cell->getParam(ID::WIDTH).as_int();
+
+ RTLIL::SigSpec new_sig_a, new_sig_s;
+ dict<RTLIL::SigBit, int> handled_bits;
+
+ // 0 and up: index of new_sig_s bit
+ // -1: const 0
+ // -2: const 1
+ std::vector<int> swizzle;
+
+ for (int i = 0; i < sig_s.size(); i++)
+ {
+ SigBit bit = sig_s[i];
+ if (bit == State::S0) {
+ swizzle.push_back(-1);
+ } else if (bit == State::S1) {
+ swizzle.push_back(-2);
+ } else {
+ auto it = handled_bits.find(bit);
+ if (it == handled_bits.end()) {
+ int new_idx = GetSize(new_sig_s);
+ new_sig_s.append(bit);
+ handled_bits[bit] = new_idx;
+ swizzle.push_back(new_idx);
+ } else {
+ swizzle.push_back(it->second);
+ }
+ }
+ }
+
+ for (int i = 0; i < (1 << GetSize(new_sig_s)); i++) {
+ int idx = 0;
+ for (int j = 0; j < GetSize(sig_s); j++) {
+ if (swizzle[j] == -1) {
+ // const 0.
+ } else if (swizzle[j] == -2) {
+ // const 1.
+ idx |= 1 << j;
+ } else {
+ if (i & 1 << swizzle[j])
+ idx |= 1 << j;
+ }
+ }
+ new_sig_a.append(sig_a.extract(idx * width, width));
+ }
+
+ if (new_sig_s.size() == 0)
+ {
+ module->connect(cell->getPort(ID::Y), new_sig_a);
+ assign_map.add(cell->getPort(ID::Y), new_sig_a);
+ module->remove(cell);
+ did_something = true;
+ total_count++;
+ return;
+ }
+
+ if (new_sig_s.size() == 1)
+ {
+ cell->type = ID($mux);
+ cell->setPort(ID::A, new_sig_a.extract(0, width));
+ cell->setPort(ID::B, new_sig_a.extract(width, width));
+ cell->setPort(ID::S, new_sig_s);
+ cell->parameters.erase(ID::S_WIDTH);
+ did_something = true;
+ total_count++;
+ return;
+ }
+
+ if (new_sig_s.size() != sig_s.size()) {
+ log(" New ctrl vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_s));
+ did_something = true;
+ total_count++;
+ cell->setPort(ID::A, new_sig_a);
+ cell->setPort(ID::S, new_sig_s);
+ cell->parameters[ID::S_WIDTH] = RTLIL::Const(new_sig_s.size());
+ }
+ }
+
+ void opt_demux(RTLIL::Cell *cell)
+ {
+ RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y));
+ RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID::S));
+ int width = cell->getParam(ID::WIDTH).as_int();
+
+ RTLIL::SigSpec new_sig_y, new_sig_s;
+ dict<RTLIL::SigBit, int> handled_bits;
+
+ // 0 and up: index of new_sig_s bit
+ // -1: const 0
+ // -2: const 1
+ std::vector<int> swizzle;
+
+ for (int i = 0; i < sig_s.size(); i++)
+ {
+ SigBit bit = sig_s[i];
+ if (bit == State::S0) {
+ swizzle.push_back(-1);
+ } else if (bit == State::S1) {
+ swizzle.push_back(-2);
+ } else {
+ auto it = handled_bits.find(bit);
+ if (it == handled_bits.end()) {
+ int new_idx = GetSize(new_sig_s);
+ new_sig_s.append(bit);
+ handled_bits[bit] = new_idx;
+ swizzle.push_back(new_idx);
+ } else {
+ swizzle.push_back(it->second);
+ }
+ }
+ }
+
+ pool<int> nonzero_idx;
+
+ for (int i = 0; i < (1 << GetSize(new_sig_s)); i++) {
+ int idx = 0;
+ for (int j = 0; j < GetSize(sig_s); j++) {
+ if (swizzle[j] == -1) {
+ // const 0.
+ } else if (swizzle[j] == -2) {
+ // const 1.
+ idx |= 1 << j;
+ } else {
+ if (i & 1 << swizzle[j])
+ idx |= 1 << j;
+ }
+ }
+ log_assert(!nonzero_idx.count(idx));
+ nonzero_idx.insert(idx);
+ new_sig_y.append(sig_y.extract(idx * width, width));
+ }
+
+ if (new_sig_s.size() == sig_s.size() && sig_s.size() > 0)
+ return;
+
+ log(" New ctrl vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_s));
+ did_something = true;
+ total_count++;
+
+ for (int i = 0; i < (1 << GetSize(sig_s)); i++) {
+ if (!nonzero_idx.count(i)) {
+ SigSpec slice = sig_y.extract(i * width, width);
+ module->connect(slice, Const(State::S0, width));
+ assign_map.add(slice, Const(State::S0, width));
+ }
+ }
+
+ if (new_sig_s.size() == 0)
+ {
+ module->connect(new_sig_y, cell->getPort(ID::A));
+ assign_map.add(new_sig_y, cell->getPort(ID::A));
+ module->remove(cell);
+ }
+ else
+ {
+ cell->setPort(ID::S, new_sig_s);
+ cell->setPort(ID::Y, new_sig_y);
+ cell->parameters[ID::S_WIDTH] = RTLIL::Const(new_sig_s.size());
+ }
+ }
+
+ bool opt_mux_bits(RTLIL::Cell *cell)
+ {
+ SigSpec sig_a = assign_map(cell->getPort(ID::A));
+ SigSpec sig_b;
+ SigSpec sig_y = assign_map(cell->getPort(ID::Y));
+ int width = GetSize(sig_y);
+
+ if (cell->type != ID($bmux))
+ sig_b = assign_map(cell->getPort(ID::B));
- std::vector<RTLIL::SigBit> new_sig_y;
RTLIL::SigSig old_sig_conn;
- std::vector<std::vector<RTLIL::SigBit>> consolidated_in_tuples;
- std::map<std::vector<RTLIL::SigBit>, RTLIL::SigBit> consolidated_in_tuples_map;
+ dict<SigSpec, SigBit> consolidated_in_tuples;
+ std::vector<int> swizzle;
- for (int i = 0; i < int(sig_y.size()); i++)
+ for (int i = 0; i < width; i++)
{
- std::vector<RTLIL::SigBit> in_tuple;
+ SigSpec in_tuple;
bool all_tuple_bits_same = true;
- in_tuple.push_back(sig_a.at(i));
- for (int j = i; j < int(sig_b.size()); j += int(sig_a.size())) {
- if (sig_b.at(j) != sig_a.at(i))
+ in_tuple.append(sig_a[i]);
+ for (int j = i; j < GetSize(sig_a); j += width) {
+ in_tuple.append(sig_a[j]);
+ if (sig_a[j] != in_tuple[0])
+ all_tuple_bits_same = false;
+ }
+ for (int j = i; j < GetSize(sig_b); j += width) {
+ in_tuple.append(sig_b[j]);
+ if (sig_b[j] != in_tuple[0])
all_tuple_bits_same = false;
- in_tuple.push_back(sig_b.at(j));
}
if (all_tuple_bits_same)
{
- old_sig_conn.first.append(sig_y.at(i));
- old_sig_conn.second.append(sig_a.at(i));
+ old_sig_conn.first.append(sig_y[i]);
+ old_sig_conn.second.append(sig_a[i]);
+ continue;
}
- else if (consolidated_in_tuples_map.count(in_tuple))
+
+ auto it = consolidated_in_tuples.find(in_tuple);
+ if (it == consolidated_in_tuples.end())
{
- old_sig_conn.first.append(sig_y.at(i));
- old_sig_conn.second.append(consolidated_in_tuples_map.at(in_tuple));
+ consolidated_in_tuples[in_tuple] = sig_y[i];
+ swizzle.push_back(i);
}
else
{
- consolidated_in_tuples_map[in_tuple] = sig_y.at(i);
- consolidated_in_tuples.push_back(in_tuple);
- new_sig_y.push_back(sig_y.at(i));
+ old_sig_conn.first.append(sig_y[i]);
+ old_sig_conn.second.append(it->second);
}
}
- if (new_sig_y.size() != sig_y.size())
+ if (GetSize(swizzle) != width)
{
log(" Consolidated identical input bits for %s cell %s:\n", cell->type.c_str(), cell->name.c_str());
- log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
- log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
-
- cell->setPort(ID::A, RTLIL::SigSpec());
- for (auto &in_tuple : consolidated_in_tuples) {
- RTLIL::SigSpec new_a = cell->getPort(ID::A);
- new_a.append(in_tuple.at(0));
- cell->setPort(ID::A, new_a);
+ if (cell->type != ID($bmux)) {
+ log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
+ log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
+ } else {
+ log(" Old ports: A=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
+ log_signal(cell->getPort(ID::Y)));
}
- cell->setPort(ID::B, RTLIL::SigSpec());
- for (int i = 1; i <= cell->getPort(ID::S).size(); i++)
- for (auto &in_tuple : consolidated_in_tuples) {
- RTLIL::SigSpec new_b = cell->getPort(ID::B);
- new_b.append(in_tuple.at(i));
- cell->setPort(ID::B, new_b);
+ if (swizzle.empty()) {
+ module->remove(cell);
+ } else {
+ SigSpec new_sig_a;
+ for (int i = 0; i < GetSize(sig_a); i += width)
+ for (int j: swizzle)
+ new_sig_a.append(sig_a[i+j]);
+ cell->setPort(ID::A, new_sig_a);
+
+ if (cell->type != ID($bmux)) {
+ SigSpec new_sig_b;
+ for (int i = 0; i < GetSize(sig_b); i += width)
+ for (int j: swizzle)
+ new_sig_b.append(sig_b[i+j]);
+ cell->setPort(ID::B, new_sig_b);
}
- cell->parameters[ID::WIDTH] = RTLIL::Const(new_sig_y.size());
- cell->setPort(ID::Y, new_sig_y);
+ SigSpec new_sig_y;
+ for (int j: swizzle)
+ new_sig_y.append(sig_y[j]);
+ cell->setPort(ID::Y, new_sig_y);
+
+ cell->parameters[ID::WIDTH] = RTLIL::Const(GetSize(swizzle));
+
+ if (cell->type != ID($bmux)) {
+ log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
+ log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
+ } else {
+ log(" New ports: A=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
+ log_signal(cell->getPort(ID::Y)));
+ }
+ }
- log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
- log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y)));
log(" New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second));
+ module->connect(old_sig_conn);
+
+ did_something = true;
+ total_count++;
+ }
+ return swizzle.empty();
+ }
+
+ bool opt_demux_bits(RTLIL::Cell *cell) {
+ SigSpec sig_a = assign_map(cell->getPort(ID::A));
+ SigSpec sig_y = assign_map(cell->getPort(ID::Y));
+ int width = GetSize(sig_a);
+
+ RTLIL::SigSig old_sig_conn;
+
+ dict<SigBit, int> handled_bits;
+ std::vector<int> swizzle;
+
+ for (int i = 0; i < width; i++)
+ {
+ if (sig_a[i] == State::S0)
+ {
+ for (int j = i; j < GetSize(sig_y); j += width)
+ {
+ old_sig_conn.first.append(sig_y[j]);
+ old_sig_conn.second.append(State::S0);
+ }
+ continue;
+ }
+ auto it = handled_bits.find(sig_a[i]);
+ if (it == handled_bits.end())
+ {
+ handled_bits[sig_a[i]] = i;
+ swizzle.push_back(i);
+ }
+ else
+ {
+ for (int j = 0; j < GetSize(sig_y); j += width)
+ {
+ old_sig_conn.first.append(sig_y[i+j]);
+ old_sig_conn.second.append(sig_y[it->second+j]);
+ }
+ }
+ }
+
+ if (GetSize(swizzle) != width)
+ {
+ log(" Consolidated identical input bits for %s cell %s:\n", cell->type.c_str(), cell->name.c_str());
+ log(" Old ports: A=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
+ log_signal(cell->getPort(ID::Y)));
+
+ if (swizzle.empty()) {
+ module->remove(cell);
+ } else {
+ SigSpec new_sig_a;
+ for (int j: swizzle)
+ new_sig_a.append(sig_a[j]);
+ cell->setPort(ID::A, new_sig_a);
+
+ SigSpec new_sig_y;
+ for (int i = 0; i < GetSize(sig_y); i += width)
+ for (int j: swizzle)
+ new_sig_y.append(sig_y[i+j]);
+ cell->setPort(ID::Y, new_sig_y);
+
+ cell->parameters[ID::WIDTH] = RTLIL::Const(GetSize(swizzle));
+
+ log(" New ports: A=%s, Y=%s\n", log_signal(cell->getPort(ID::A)),
+ log_signal(cell->getPort(ID::Y)));
+ }
+
+ log(" New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second));
module->connect(old_sig_conn);
did_something = true;
total_count++;
}
+ return swizzle.empty();
}
OptReduceWorker(RTLIL::Design *design, RTLIL::Module *module, bool do_fine) :
@@ -254,9 +520,9 @@ struct OptReduceWorker
SigPool mem_wren_sigs;
for (auto &cell_it : module->cells_) {
RTLIL::Cell *cell = cell_it.second;
- if (cell->type == ID($mem))
+ if (cell->type.in(ID($mem), ID($mem_v2)))
mem_wren_sigs.add(assign_map(cell->getPort(ID::WR_EN)));
- if (cell->type == ID($memwr))
+ if (cell->type.in(ID($memwr), ID($memwr_v2)))
mem_wren_sigs.add(assign_map(cell->getPort(ID::EN)));
}
for (auto &cell_it : module->cells_) {
@@ -309,20 +575,31 @@ struct OptReduceWorker
// merge identical inputs on $mux and $pmux cells
- std::vector<RTLIL::Cell*> cells;
-
- for (auto &it : module->cells_)
- if ((it.second->type == ID($mux) || it.second->type == ID($pmux)) && design->selected(module, it.second))
- cells.push_back(it.second);
-
- for (auto cell : cells)
+ for (auto cell : module->selected_cells())
{
+ if (!cell->type.in(ID($mux), ID($pmux), ID($bmux), ID($demux)))
+ continue;
+
// this optimization is to aggressive for most coarse-grain applications.
// but we always want it for multiplexers driving write enable ports.
- if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(ID::Y))))
- opt_mux_bits(cell);
+ if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(ID::Y)))) {
+ if (cell->type == ID($demux)) {
+ if (opt_demux_bits(cell))
+ continue;
+ } else {
+ if (opt_mux_bits(cell))
+ continue;
+ }
+ }
+
+ if (cell->type.in(ID($mux), ID($pmux)))
+ opt_pmux(cell);
+
+ if (cell->type == ID($bmux))
+ opt_bmux(cell);
- opt_mux(cell);
+ if (cell->type == ID($demux))
+ opt_demux(cell);
}
}
diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc
index 62a478673..ba85df975 100644
--- a/passes/opt/opt_share.cc
+++ b/passes/opt/opt_share.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* 2019 Bogdan Vukobratovic <bogdan.vukobratovic@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc
index f3b1fd377..90ddf8dd7 100644
--- a/passes/opt/pmux2shiftx.cc
+++ b/passes/opt/pmux2shiftx.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/opt/rmports.cc b/passes/opt/rmports.cc
index 99a2a61c8..9fa9f5c2d 100644
--- a/passes/opt/rmports.cc
+++ b/passes/opt/rmports.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/opt/share.cc b/passes/opt/share.cc
index f7848e01d..abef71937 100644
--- a/passes/opt/share.cc
+++ b/passes/opt/share.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -18,7 +18,7 @@
*/
#include "kernel/yosys.h"
-#include "kernel/satgen.h"
+#include "kernel/qcsat.h"
#include "kernel/sigtools.h"
#include "kernel/modtools.h"
#include "kernel/utils.h"
@@ -58,8 +58,6 @@ struct ShareWorker
std::map<RTLIL::Cell*, std::set<RTLIL::Cell*, cell_ptr_cmp>, cell_ptr_cmp> topo_cell_drivers;
std::map<RTLIL::SigBit, std::set<RTLIL::Cell*, cell_ptr_cmp>> topo_bit_drivers;
- std::vector<std::pair<RTLIL::SigBit, RTLIL::SigBit>> exclusive_ctrls;
-
// ------------------------------------------------------------------------------
// Find terminal bits -- i.e. bits that do not (exclusively) feed into a mux tree
@@ -368,7 +366,7 @@ struct ShareWorker
continue;
}
- if (cell->type == ID($memrd)) {
+ if (cell->type.in(ID($memrd), ID($memrd_v2))) {
if (cell->parameters.at(ID::CLK_ENABLE).as_bool())
continue;
if (config.opt_aggressive || !modwalker.sigmap(cell->getPort(ID::ADDR)).is_fully_const())
@@ -401,11 +399,14 @@ struct ShareWorker
if (c1->type != c2->type)
return false;
- if (c1->type == ID($memrd))
+ if (c1->type.in(ID($memrd), ID($memrd_v2)))
{
if (c1->parameters.at(ID::MEMID).decode_string() != c2->parameters.at(ID::MEMID).decode_string())
return false;
+ if (c1->parameters.at(ID::WIDTH) != c2->parameters.at(ID::WIDTH))
+ return false;
+
return true;
}
@@ -705,7 +706,7 @@ struct ShareWorker
return supercell;
}
- if (c1->type == ID($memrd))
+ if (c1->type.in(ID($memrd), ID($memrd_v2)))
{
RTLIL::Cell *supercell = module->addCell(NEW_ID, c1);
RTLIL::SigSpec addr1 = c1->getPort(ID::ADDR);
@@ -1156,7 +1157,6 @@ struct ShareWorker
recursion_state.clear();
topo_cell_drivers.clear();
topo_bit_drivers.clear();
- exclusive_ctrls.clear();
terminal_bits.clear();
shareable_cells.clear();
forbidden_controls_cache.clear();
@@ -1171,13 +1171,6 @@ struct ShareWorker
log("Found %d cells in module %s that may be considered for resource sharing.\n",
GetSize(shareable_cells), log_id(module));
- for (auto cell : module->cells())
- if (cell->type == ID($pmux))
- for (auto bit : cell->getPort(ID::S))
- for (auto other_bit : cell->getPort(ID::S))
- if (bit < other_bit)
- exclusive_ctrls.push_back(std::pair<RTLIL::SigBit, RTLIL::SigBit>(bit, other_bit));
-
while (!shareable_cells.empty() && config.limit != 0)
{
RTLIL::Cell *cell = *shareable_cells.begin();
@@ -1256,8 +1249,11 @@ struct ShareWorker
optimize_activation_patterns(filtered_cell_activation_patterns);
optimize_activation_patterns(filtered_other_cell_activation_patterns);
- ezSatPtr ez;
- SatGen satgen(ez.get(), &modwalker.sigmap);
+ QuickConeSat qcsat(modwalker);
+ if (config.opt_fast) {
+ qcsat.max_cell_outs = 3;
+ qcsat.max_cell_count = 100;
+ }
pool<RTLIL::Cell*> sat_cells;
std::set<RTLIL::SigBit> bits_queue;
@@ -1267,77 +1263,45 @@ struct ShareWorker
for (auto &p : filtered_cell_activation_patterns) {
log(" Activation pattern for cell %s: %s = %s\n", log_id(cell), log_signal(p.first), log_signal(p.second));
- cell_active.push_back(ez->vec_eq(satgen.importSigSpec(p.first), satgen.importSigSpec(p.second)));
+ cell_active.push_back(qcsat.ez->vec_eq(qcsat.importSig(p.first), qcsat.importSig(p.second)));
all_ctrl_signals.append(p.first);
}
for (auto &p : filtered_other_cell_activation_patterns) {
log(" Activation pattern for cell %s: %s = %s\n", log_id(other_cell), log_signal(p.first), log_signal(p.second));
- other_cell_active.push_back(ez->vec_eq(satgen.importSigSpec(p.first), satgen.importSigSpec(p.second)));
+ other_cell_active.push_back(qcsat.ez->vec_eq(qcsat.importSig(p.first), qcsat.importSig(p.second)));
all_ctrl_signals.append(p.first);
}
- for (auto &bit : cell_activation_signals.to_sigbit_vector())
- bits_queue.insert(bit);
-
- for (auto &bit : other_cell_activation_signals.to_sigbit_vector())
- bits_queue.insert(bit);
-
- while (!bits_queue.empty())
- {
- pool<ModWalker::PortBit> portbits;
- modwalker.get_drivers(portbits, bits_queue);
- bits_queue.clear();
-
- for (auto &pbit : portbits)
- if (sat_cells.count(pbit.cell) == 0 && cone_ct.cell_known(pbit.cell->type)) {
- if (config.opt_fast && modwalker.cell_outputs[pbit.cell].size() >= 4)
- continue;
- // log(" Adding cell %s (%s) to SAT problem.\n", log_id(pbit.cell), log_id(pbit.cell->type));
- bits_queue.insert(modwalker.cell_inputs[pbit.cell].begin(), modwalker.cell_inputs[pbit.cell].end());
- satgen.importCell(pbit.cell);
- sat_cells.insert(pbit.cell);
- }
-
- if (config.opt_fast && sat_cells.size() > 100)
- break;
- }
-
- for (auto it : exclusive_ctrls)
- if (satgen.importedSigBit(it.first) && satgen.importedSigBit(it.second)) {
- log(" Adding exclusive control bits: %s vs. %s\n", log_signal(it.first), log_signal(it.second));
- int sub1 = satgen.importSigBit(it.first);
- int sub2 = satgen.importSigBit(it.second);
- ez->assume(ez->NOT(ez->AND(sub1, sub2)));
- }
+ qcsat.prepare();
- if (!ez->solve(ez->expression(ez->OpOr, cell_active))) {
+ int sub1 = qcsat.ez->expression(qcsat.ez->OpOr, cell_active);
+ if (!qcsat.ez->solve(sub1)) {
log(" According to the SAT solver the cell %s is never active. Sharing is pointless, we simply remove it.\n", log_id(cell));
cells_to_remove.insert(cell);
break;
}
- if (!ez->solve(ez->expression(ez->OpOr, other_cell_active))) {
+ int sub2 = qcsat.ez->expression(qcsat.ez->OpOr, other_cell_active);
+ if (!qcsat.ez->solve(sub2)) {
log(" According to the SAT solver the cell %s is never active. Sharing is pointless, we simply remove it.\n", log_id(other_cell));
cells_to_remove.insert(other_cell);
shareable_cells.erase(other_cell);
continue;
}
- ez->non_incremental();
+ qcsat.ez->non_incremental();
all_ctrl_signals.sort_and_unify();
- std::vector<int> sat_model = satgen.importSigSpec(all_ctrl_signals);
+ std::vector<int> sat_model = qcsat.importSig(all_ctrl_signals);
std::vector<bool> sat_model_values;
- int sub1 = ez->expression(ez->OpOr, cell_active);
- int sub2 = ez->expression(ez->OpOr, other_cell_active);
- ez->assume(ez->AND(sub1, sub2));
+ qcsat.ez->assume(qcsat.ez->AND(sub1, sub2));
log(" Size of SAT problem: %d cells, %d variables, %d clauses\n",
- GetSize(sat_cells), ez->numCnfVariables(), ez->numCnfClauses());
+ GetSize(sat_cells), qcsat.ez->numCnfVariables(), qcsat.ez->numCnfClauses());
- if (ez->solve(sat_model, sat_model_values)) {
+ if (qcsat.ez->solve(sat_model, sat_model_values)) {
log(" According to the SAT solver this pair of cells can not be shared.\n");
log(" Model from SAT solver: %s = %d'", log_signal(all_ctrl_signals), GetSize(sat_model_values));
for (int i = GetSize(sat_model_values)-1; i >= 0; i--)
diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc
index a216f36d4..aaad28ef0 100644
--- a/passes/opt/wreduce.cc
+++ b/passes/opt/wreduce.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -558,7 +558,7 @@ struct WreducePass : public Pass {
}
}
- if (!opt_memx && c->type.in(ID($memrd), ID($memwr), ID($meminit))) {
+ if (!opt_memx && c->type.in(ID($memrd), ID($memrd_v2), ID($memwr), ID($memwr_v2), ID($meminit), ID($meminit_v2))) {
IdString memid = c->getParam(ID::MEMID).decode_string();
RTLIL::Memory *mem = module->memories.at(memid);
if (mem->start_offset >= 0) {
diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc
index c6bbc386a..a7ef64282 100644
--- a/passes/pmgen/Makefile.inc
+++ b/passes/pmgen/Makefile.inc
@@ -4,24 +4,31 @@
# --------------------------------------
OBJS += passes/pmgen/test_pmgen.o
+GENFILES += passes/pmgen/test_pmgen_pm.h
passes/pmgen/test_pmgen.o: passes/pmgen/test_pmgen_pm.h passes/pmgen/ice40_dsp_pm.h passes/pmgen/peepopt_pm.h passes/pmgen/xilinx_srl_pm.h
$(eval $(call add_extra_objs,passes/pmgen/test_pmgen_pm.h))
# --------------------------------------
OBJS += passes/pmgen/ice40_dsp.o
+GENFILES += passes/pmgen/ice40_dsp_pm.h
passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h
$(eval $(call add_extra_objs,passes/pmgen/ice40_dsp_pm.h))
# --------------------------------------
OBJS += passes/pmgen/ice40_wrapcarry.o
+GENFILES += passes/pmgen/ice40_wrapcarry_pm.h
passes/pmgen/ice40_wrapcarry.o: passes/pmgen/ice40_wrapcarry_pm.h
$(eval $(call add_extra_objs,passes/pmgen/ice40_wrapcarry_pm.h))
# --------------------------------------
OBJS += passes/pmgen/xilinx_dsp.o
+GENFILES += passes/pmgen/xilinx_dsp_pm.h
+GENFILES += passes/pmgen/xilinx_dsp48a_pm.h
+GENFILES += passes/pmgen/xilinx_dsp_CREG_pm.h
+GENFILES += passes/pmgen/xilinx_dsp_cascade_pm.h
passes/pmgen/xilinx_dsp.o: passes/pmgen/xilinx_dsp_pm.h passes/pmgen/xilinx_dsp48a_pm.h passes/pmgen/xilinx_dsp_CREG_pm.h passes/pmgen/xilinx_dsp_cascade_pm.h
$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_pm.h))
$(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp48a_pm.h))
@@ -31,6 +38,7 @@ $(eval $(call add_extra_objs,passes/pmgen/xilinx_dsp_cascade_pm.h))
# --------------------------------------
OBJS += passes/pmgen/peepopt.o
+GENFILES += passes/pmgen/peepopt_pm.h
passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h
$(eval $(call add_extra_objs,passes/pmgen/peepopt_pm.h))
@@ -43,5 +51,6 @@ passes/pmgen/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN)
# --------------------------------------
OBJS += passes/pmgen/xilinx_srl.o
+GENFILES += passes/pmgen/xilinx_srl_pm.h
passes/pmgen/xilinx_srl.o: passes/pmgen/xilinx_srl_pm.h
$(eval $(call add_extra_objs,passes/pmgen/xilinx_srl_pm.h))
diff --git a/passes/pmgen/generate.h b/passes/pmgen/generate.h
index 354583de5..85e208774 100644
--- a/passes/pmgen/generate.h
+++ b/passes/pmgen/generate.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc
index c46f5d58f..24134b1fb 100644
--- a/passes/pmgen/ice40_dsp.cc
+++ b/passes/pmgen/ice40_dsp.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg
index 7a01cbd51..4de479122 100644
--- a/passes/pmgen/ice40_dsp.pmg
+++ b/passes/pmgen/ice40_dsp.pmg
@@ -28,9 +28,8 @@ code sigA sigB sigH
for (i = GetSize(sig)-1; i > 0; i--)
if (sig[i] != sig[i-1])
break;
- // Do not remove non-const sign bit
- if (sig[i].wire)
- ++i;
+ // Do not remove sign bit
+ ++i;
return sig.extract(0, i);
};
sigA = unextend(port(mul, \A));
diff --git a/passes/pmgen/ice40_wrapcarry.cc b/passes/pmgen/ice40_wrapcarry.cc
index e234906ad..c936d02dc 100644
--- a/passes/pmgen/ice40_wrapcarry.cc
+++ b/passes/pmgen/ice40_wrapcarry.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/pmgen/peepopt.cc b/passes/pmgen/peepopt.cc
index a9c62fcf6..9a497c914 100644
--- a/passes/pmgen/peepopt.cc
+++ b/passes/pmgen/peepopt.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/pmgen/test_pmgen.cc b/passes/pmgen/test_pmgen.cc
index 7b2938ddf..beff59778 100644
--- a/passes/pmgen/test_pmgen.cc
+++ b/passes/pmgen/test_pmgen.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc
index cf7703d36..72b4522d8 100644
--- a/passes/pmgen/xilinx_dsp.cc
+++ b/passes/pmgen/xilinx_dsp.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/pmgen/xilinx_srl.cc b/passes/pmgen/xilinx_srl.cc
index 1410850c7..a66a06586 100644
--- a/passes/pmgen/xilinx_srl.cc
+++ b/passes/pmgen/xilinx_srl.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* (C) 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/proc/Makefile.inc b/passes/proc/Makefile.inc
index 4b56979f8..50244bf33 100644
--- a/passes/proc/Makefile.inc
+++ b/passes/proc/Makefile.inc
@@ -8,3 +8,4 @@ OBJS += passes/proc/proc_arst.o
OBJS += passes/proc/proc_mux.o
OBJS += passes/proc/proc_dlatch.o
OBJS += passes/proc/proc_dff.o
+OBJS += passes/proc/proc_memwr.o
diff --git a/passes/proc/proc.cc b/passes/proc/proc.cc
index 09cf0af82..d7aac57b6 100644
--- a/passes/proc/proc.cc
+++ b/passes/proc/proc.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -43,7 +43,9 @@ struct ProcPass : public Pass {
log(" proc_mux\n");
log(" proc_dlatch\n");
log(" proc_dff\n");
+ log(" proc_memwr\n");
log(" proc_clean\n");
+ log(" opt_expr -keepdc\n");
log("\n");
log("This replaces the processes in the design with multiplexers,\n");
log("flip-flops and latches.\n");
@@ -60,12 +62,16 @@ struct ProcPass : public Pass {
log(" This option is passed through to proc_mux. proc_rmdead is not\n");
log(" executed in -ifx mode.\n");
log("\n");
+ log(" -noopt\n");
+ log(" Will omit the opt_expr pass.\n");
+ log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
std::string global_arst;
bool ifxmode = false;
bool nomux = false;
+ bool noopt = false;
log_header(design, "Executing PROC pass (convert processes to netlists).\n");
log_push();
@@ -85,6 +91,10 @@ struct ProcPass : public Pass {
ifxmode = true;
continue;
}
+ if (args[argidx] == "-noopt") {
+ noopt = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -102,7 +112,10 @@ struct ProcPass : public Pass {
Pass::call(design, ifxmode ? "proc_mux -ifx" : "proc_mux");
Pass::call(design, "proc_dlatch");
Pass::call(design, "proc_dff");
+ Pass::call(design, "proc_memwr");
Pass::call(design, "proc_clean");
+ if (!noopt)
+ Pass::call(design, "opt_expr -keepdc");
log_pop();
}
diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc
index 16db461b2..f01682957 100644
--- a/passes/proc/proc_arst.cc
+++ b/passes/proc/proc_arst.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -153,51 +153,93 @@ void eliminate_const(RTLIL::Module *mod, RTLIL::CaseRule *cs, RTLIL::SigSpec con
}
}
+RTLIL::SigSpec apply_reset(RTLIL::Module *mod, RTLIL::Process *proc, RTLIL::SyncRule *sync, SigMap &assign_map, RTLIL::SigSpec root_sig, bool polarity, RTLIL::SigSpec sig, RTLIL::SigSpec log_sig) {
+ RTLIL::SigSpec rspec = assign_map(sig);
+ RTLIL::SigSpec rval = RTLIL::SigSpec(RTLIL::State::Sm, rspec.size());
+ for (int i = 0; i < GetSize(rspec); i++)
+ if (rspec[i].wire == NULL)
+ rval[i] = rspec[i];
+ RTLIL::SigSpec last_rval;
+ for (int count = 0; rval != last_rval; count++) {
+ last_rval = rval;
+ apply_const(mod, rspec, rval, &proc->root_case, root_sig, polarity, false);
+ assign_map.apply(rval);
+ if (rval.is_fully_const())
+ break;
+ if (count > 100)
+ log_error("Async reset %s yields endless loop at value %s for signal %s.\n",
+ log_signal(sync->signal), log_signal(rval), log_signal(log_sig));
+ rspec = rval;
+ }
+ if (rval.has_marked_bits())
+ log_error("Async reset %s yields non-constant value %s for signal %s.\n",
+ log_signal(sync->signal), log_signal(rval), log_signal(log_sig));
+ return rval;
+}
+
void proc_arst(RTLIL::Module *mod, RTLIL::Process *proc, SigMap &assign_map)
{
-restart_proc_arst:
- if (proc->root_case.switches.size() != 1)
- return;
-
- RTLIL::SigSpec root_sig = proc->root_case.switches[0]->signal;
+ std::vector<RTLIL::SyncRule *> arst_syncs;
+ std::vector<RTLIL::SyncRule *> edge_syncs;
+ std::vector<RTLIL::SyncRule *> other_syncs;
for (auto &sync : proc->syncs) {
- if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn) {
+ if (sync->type == RTLIL::SyncType::ST0 || sync->type == RTLIL::SyncType::ST1) {
+ arst_syncs.push_back(sync);
+ } else if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn) {
+ edge_syncs.push_back(sync);
+ } else {
+ other_syncs.push_back(sync);
+ }
+ }
+
+ bool did_something = false;
+
+ while (proc->root_case.switches.size() == 1) {
+ RTLIL::SigSpec root_sig = proc->root_case.switches[0]->signal;
+
+ bool found = false;
+ for (auto it = edge_syncs.begin(); it != edge_syncs.end(); ++it) {
+ auto sync = *it;
bool polarity = sync->type == RTLIL::SyncType::STp;
if (check_signal(mod, root_sig, sync->signal, polarity)) {
- if (proc->syncs.size() == 1) {
- log("Found VHDL-style edge-trigger %s in `%s.%s'.\n", log_signal(sync->signal), mod->name.c_str(), proc->name.c_str());
- } else {
+ if (edge_syncs.size() > 1) {
log("Found async reset %s in `%s.%s'.\n", log_signal(sync->signal), mod->name.c_str(), proc->name.c_str());
sync->type = sync->type == RTLIL::SyncType::STp ? RTLIL::SyncType::ST1 : RTLIL::SyncType::ST0;
- }
- for (auto &action : sync->actions) {
- RTLIL::SigSpec rspec = assign_map(action.second);
- RTLIL::SigSpec rval = RTLIL::SigSpec(RTLIL::State::Sm, rspec.size());
- for (int i = 0; i < GetSize(rspec); i++)
- if (rspec[i].wire == NULL)
- rval[i] = rspec[i];
- RTLIL::SigSpec last_rval;
- for (int count = 0; rval != last_rval; count++) {
- last_rval = rval;
- apply_const(mod, rspec, rval, &proc->root_case, root_sig, polarity, false);
- assign_map.apply(rval);
- if (rval.is_fully_const())
- break;
- if (count > 100)
- log_error("Async reset %s yields endless loop at value %s for signal %s.\n",
- log_signal(sync->signal), log_signal(rval), log_signal(action.first));
- rspec = rval;
+ arst_syncs.push_back(sync);
+ edge_syncs.erase(it);
+ for (auto &action : sync->actions) {
+ action.second = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, action.second, action.first);
+ }
+ for (auto &memwr : sync->mem_write_actions) {
+ RTLIL::SigSpec en = apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.enable, memwr.enable);
+ if (!en.is_fully_zero()) {
+ log_error("Async reset %s causes memory write to %s.\n",
+ log_signal(sync->signal), log_id(memwr.memid));
+ }
+ apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.address, memwr.address);
+ apply_reset(mod, proc, sync, assign_map, root_sig, polarity, memwr.data, memwr.data);
}
- if (rval.has_marked_bits())
- log_error("Async reset %s yields non-constant value %s for signal %s.\n",
- log_signal(sync->signal), log_signal(rval), log_signal(action.first));
- action.second = rval;
+ sync->mem_write_actions.clear();
+ eliminate_const(mod, &proc->root_case, root_sig, polarity);
+ } else {
+ log("Found VHDL-style edge-trigger %s in `%s.%s'.\n", log_signal(sync->signal), mod->name.c_str(), proc->name.c_str());
+ eliminate_const(mod, &proc->root_case, root_sig, !polarity);
}
- eliminate_const(mod, &proc->root_case, root_sig, polarity);
- goto restart_proc_arst;
+ did_something = true;
+ found = true;
+ break;
}
}
+ if (!found)
+ break;
+ }
+
+ if (did_something) {
+ proc->syncs.clear();
+ proc->syncs.insert(proc->syncs.end(), arst_syncs.begin(), arst_syncs.end());
+ proc->syncs.insert(proc->syncs.end(), edge_syncs.begin(), edge_syncs.end());
+ proc->syncs.insert(proc->syncs.end(), other_syncs.begin(), other_syncs.end());
}
}
diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc
index 5e78b7316..45872907b 100644
--- a/passes/proc/proc_clean.cc
+++ b/passes/proc/proc_clean.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -76,22 +76,33 @@ void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did
}
else
{
- bool all_fully_def = true;
for (auto cs : sw->cases)
- {
if (max_depth != 0)
proc_clean_case(cs, did_something, count, max_depth-1);
- int size = 0;
- for (auto cmp : cs->compare)
+
+ bool is_parallel_case = sw->get_bool_attribute(ID::parallel_case);
+ bool is_full_case = sw->get_bool_attribute(ID::full_case);
+
+ // Empty case removal. The rules are:
+ //
+ // - for full_case: only remove cases if *all* cases are empty
+ // - for parallel_case but not full_case: remove any empty case
+ // - for non-parallel and non-full case: remove the final case if it's empty
+
+ if (is_full_case)
+ {
+ bool all_empty = true;
+ for (auto cs : sw->cases)
+ if (!cs->empty())
+ all_empty = false;
+ if (all_empty)
{
- size += cmp.size();
- if (!cmp.is_fully_def())
- all_fully_def = false;
+ for (auto cs : sw->cases)
+ delete cs;
+ sw->cases.clear();
}
- if (sw->signal.size() != size)
- all_fully_def = false;
}
- if (all_fully_def)
+ else if (is_parallel_case)
{
for (auto cs = sw->cases.begin(); cs != sw->cases.end();)
{
@@ -150,7 +161,7 @@ void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count, bool
for (size_t j = 0; j < proc->syncs[i]->actions.size(); j++)
if (proc->syncs[i]->actions[j].first.size() == 0)
proc->syncs[i]->actions.erase(proc->syncs[i]->actions.begin() + (j--));
- if (proc->syncs[i]->actions.size() == 0) {
+ if (proc->syncs[i]->actions.size() == 0 && proc->syncs[i]->mem_write_actions.size() == 0) {
delete proc->syncs[i];
proc->syncs.erase(proc->syncs.begin() + (i--));
}
@@ -198,7 +209,7 @@ struct ProcCleanPass : public Pass {
extra_args(args, argidx, design);
for (auto mod : design->modules()) {
- std::vector<RTLIL::IdString> delme;
+ std::vector<RTLIL::Process *> delme;
if (!design->selected(mod))
continue;
for (auto &proc_it : mod->processes) {
@@ -209,12 +220,11 @@ struct ProcCleanPass : public Pass {
proc_it.second->root_case.actions.size() == 0) {
if (!quiet)
log("Removing empty process `%s.%s'.\n", log_id(mod), proc_it.second->name.c_str());
- delme.push_back(proc_it.first);
+ delme.push_back(proc_it.second);
}
}
- for (auto &id : delme) {
- delete mod->processes[id];
- mod->processes.erase(id);
+ for (auto proc : delme) {
+ mod->remove(proc);
}
}
diff --git a/passes/proc/proc_dff.cc b/passes/proc/proc_dff.cc
index e320a72a6..234671df5 100644
--- a/passes/proc/proc_dff.cc
+++ b/passes/proc/proc_dff.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -143,48 +143,23 @@ void gen_dffsr_complex(RTLIL::Module *mod, RTLIL::SigSpec sig_d, RTLIL::SigSpec
cell->type.c_str(), cell->name.c_str(), clk_polarity ? "positive" : "negative");
}
-void gen_dffsr(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_out,
+void gen_aldff(RTLIL::Module *mod, RTLIL::SigSpec sig_in, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_out,
bool clk_polarity, bool set_polarity, RTLIL::SigSpec clk, RTLIL::SigSpec set, RTLIL::Process *proc)
{
std::stringstream sstr;
sstr << "$procdff$" << (autoidx++);
- RTLIL::SigSpec sig_set_inv = mod->addWire(NEW_ID, sig_in.size());
- RTLIL::SigSpec sig_sr_set = mod->addWire(NEW_ID, sig_in.size());
- RTLIL::SigSpec sig_sr_clr = mod->addWire(NEW_ID, sig_in.size());
-
- RTLIL::Cell *inv_set = mod->addCell(NEW_ID, ID($not));
- inv_set->parameters[ID::A_SIGNED] = RTLIL::Const(0);
- inv_set->parameters[ID::A_WIDTH] = RTLIL::Const(sig_in.size());
- inv_set->parameters[ID::Y_WIDTH] = RTLIL::Const(sig_in.size());
- inv_set->setPort(ID::A, sig_set);
- inv_set->setPort(ID::Y, sig_set_inv);
-
- RTLIL::Cell *mux_sr_set = mod->addCell(NEW_ID, ID($mux));
- mux_sr_set->parameters[ID::WIDTH] = RTLIL::Const(sig_in.size());
- mux_sr_set->setPort(set_polarity ? ID::A : ID::B, RTLIL::Const(0, sig_in.size()));
- mux_sr_set->setPort(set_polarity ? ID::B : ID::A, sig_set);
- mux_sr_set->setPort(ID::Y, sig_sr_set);
- mux_sr_set->setPort(ID::S, set);
-
- RTLIL::Cell *mux_sr_clr = mod->addCell(NEW_ID, ID($mux));
- mux_sr_clr->parameters[ID::WIDTH] = RTLIL::Const(sig_in.size());
- mux_sr_clr->setPort(set_polarity ? ID::A : ID::B, RTLIL::Const(0, sig_in.size()));
- mux_sr_clr->setPort(set_polarity ? ID::B : ID::A, sig_set_inv);
- mux_sr_clr->setPort(ID::Y, sig_sr_clr);
- mux_sr_clr->setPort(ID::S, set);
-
- RTLIL::Cell *cell = mod->addCell(sstr.str(), ID($dffsr));
+ RTLIL::Cell *cell = mod->addCell(sstr.str(), ID($aldff));
cell->attributes = proc->attributes;
+
cell->parameters[ID::WIDTH] = RTLIL::Const(sig_in.size());
+ cell->parameters[ID::ALOAD_POLARITY] = RTLIL::Const(set_polarity, 1);
cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity, 1);
- cell->parameters[ID::SET_POLARITY] = RTLIL::Const(true, 1);
- cell->parameters[ID::CLR_POLARITY] = RTLIL::Const(true, 1);
cell->setPort(ID::D, sig_in);
cell->setPort(ID::Q, sig_out);
+ cell->setPort(ID::AD, sig_set);
cell->setPort(ID::CLK, clk);
- cell->setPort(ID::SET, sig_sr_set);
- cell->setPort(ID::CLR, sig_sr_clr);
+ cell->setPort(ID::ALOAD, set);
log(" created %s cell `%s' with %s edge clock and %s level non-const reset.\n", cell->type.c_str(), cell->name.c_str(),
clk_polarity ? "positive" : "negative", set_polarity ? "positive" : "negative");
@@ -328,6 +303,10 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce)
ce.assign_map.apply(sig);
if (rstval == sig) {
+ if (sync_level->type == RTLIL::SyncType::ST1)
+ insig = mod->Mux(NEW_ID, insig, sig, sync_level->signal);
+ else
+ insig = mod->Mux(NEW_ID, sig, insig, sync_level->signal);
rstval = RTLIL::SigSpec(RTLIL::State::Sz, sig.size());
sync_level = NULL;
}
@@ -351,7 +330,7 @@ void proc_dff(RTLIL::Module *mod, RTLIL::Process *proc, ConstEval &ce)
else if (!rstval.is_fully_const() && !ce.eval(rstval))
{
log_warning("Async reset value `%s' is not constant!\n", log_signal(rstval));
- gen_dffsr(mod, insig, rstval, sig_q,
+ gen_aldff(mod, insig, rstval, sig_q,
sync_edge->type == RTLIL::SyncType::STp,
sync_level && sync_level->type == RTLIL::SyncType::ST1,
sync_edge->signal, sync_level->signal, proc);
diff --git a/passes/proc/proc_dlatch.cc b/passes/proc/proc_dlatch.cc
index 7b8c05b21..8340e1431 100644
--- a/passes/proc/proc_dlatch.cc
+++ b/passes/proc/proc_dlatch.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -342,7 +342,6 @@ struct proc_dlatch_db_t
void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
{
- std::vector<RTLIL::SyncRule*> new_syncs;
RTLIL::SigSig latches_bits, nolatches_bits;
dict<SigBit, SigBit> latches_out_in;
dict<SigBit, int> latches_hold;
@@ -351,7 +350,6 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
for (auto sr : proc->syncs)
{
if (sr->type != RTLIL::SyncType::STa) {
- new_syncs.push_back(sr);
continue;
}
@@ -373,8 +371,7 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
for (int i = 0; i < GetSize(ss.first); i++)
latches_out_in[ss.first[i]] = ss.second[i];
}
-
- delete sr;
+ sr->actions.clear();
}
latches_out_in.sort();
@@ -441,8 +438,6 @@ void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
offset += width;
}
-
- new_syncs.swap(proc->syncs);
}
struct ProcDlatchPass : public Pass {
diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc
index eb323038d..4da20c395 100644
--- a/passes/proc/proc_init.cc
+++ b/passes/proc/proc_init.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -28,12 +28,9 @@ PRIVATE_NAMESPACE_BEGIN
void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc)
{
- bool found_init = false;
-
for (auto &sync : proc->syncs)
if (sync->type == RTLIL::SyncType::STi)
{
- found_init = true;
log("Found init rule in `%s.%s'.\n", mod->name.c_str(), proc->name.c_str());
for (auto &action : sync->actions)
@@ -71,17 +68,8 @@ void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc)
offset += lhs_c.width;
}
}
+ sync->actions.clear();
}
-
- if (found_init) {
- std::vector<RTLIL::SyncRule*> new_syncs;
- for (auto &sync : proc->syncs)
- if (sync->type == RTLIL::SyncType::STi)
- delete sync;
- else
- new_syncs.push_back(sync);
- proc->syncs.swap(new_syncs);
- }
}
struct ProcInitPass : public Pass {
diff --git a/passes/proc/proc_memwr.cc b/passes/proc/proc_memwr.cc
new file mode 100644
index 000000000..cf10bd4b2
--- /dev/null
+++ b/passes/proc/proc_memwr.cc
@@ -0,0 +1,121 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * 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/register.h"
+#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
+#include "kernel/consteval.h"
+#include "kernel/log.h"
+#include <sstream>
+#include <stdlib.h>
+#include <stdio.h>
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+void proc_memwr(RTLIL::Module *mod, RTLIL::Process *proc, dict<IdString, int> &next_port_id)
+{
+ for (auto sr : proc->syncs)
+ {
+ std::vector<int> prev_port_ids;
+ for (auto memwr : sr->mem_write_actions) {
+ int port_id = next_port_id[memwr.memid]++;
+ Const priority_mask(State::S0, port_id);
+ for (int i = 0; i < GetSize(prev_port_ids); i++)
+ if (memwr.priority_mask[i] == State::S1)
+ priority_mask[prev_port_ids[i]] = State::S1;
+ prev_port_ids.push_back(port_id);
+
+ RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($memwr_v2));
+ cell->attributes = memwr.attributes;
+ cell->setParam(ID::MEMID, Const(memwr.memid.str()));
+ cell->setParam(ID::ABITS, GetSize(memwr.address));
+ cell->setParam(ID::WIDTH, GetSize(memwr.data));
+ cell->setParam(ID::PORTID, port_id);
+ cell->setParam(ID::PRIORITY_MASK, priority_mask);
+ cell->setPort(ID::ADDR, memwr.address);
+ cell->setPort(ID::DATA, memwr.data);
+ SigSpec enable = memwr.enable;
+ for (auto sr2 : proc->syncs) {
+ if (sr2->type == RTLIL::SyncType::ST0) {
+ log_assert(sr2->mem_write_actions.empty());
+ enable = mod->Mux(NEW_ID, Const(State::S0, GetSize(enable)), enable, sr2->signal);
+ } else if (sr2->type == RTLIL::SyncType::ST1) {
+ log_assert(sr2->mem_write_actions.empty());
+ enable = mod->Mux(NEW_ID, enable, Const(State::S0, GetSize(enable)), sr2->signal);
+ }
+ }
+ cell->setPort(ID::EN, enable);
+ if (sr->type == RTLIL::SyncType::STa) {
+ cell->setPort(ID::CLK, State::Sx);
+ cell->setParam(ID::CLK_ENABLE, State::S0);
+ cell->setParam(ID::CLK_POLARITY, State::Sx);
+ } else if (sr->type == RTLIL::SyncType::STp) {
+ cell->setPort(ID::CLK, sr->signal);
+ cell->setParam(ID::CLK_ENABLE, State::S1);
+ cell->setParam(ID::CLK_POLARITY, State::S1);
+ } else if (sr->type == RTLIL::SyncType::STn) {
+ cell->setPort(ID::CLK, sr->signal);
+ cell->setParam(ID::CLK_ENABLE, State::S1);
+ cell->setParam(ID::CLK_POLARITY, State::S0);
+ } else {
+ log_error("process memory write with unsupported sync type in %s.%s", log_id(mod), log_id(proc));
+ }
+ }
+ sr->mem_write_actions.clear();
+ }
+}
+
+struct ProcMemWrPass : public Pass {
+ ProcMemWrPass() : Pass("proc_memwr", "extract memory writes from processes") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" proc_memwr [selection]\n");
+ log("\n");
+ log("This pass converts memory writes in processes into $memwr cells.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing PROC_MEMWR pass (convert process memory writes to cells).\n");
+
+ extra_args(args, 1, design);
+
+ for (auto module : design->selected_modules()) {
+ dict<IdString, int> next_port_id;
+ for (auto cell : module->cells()) {
+ if (cell->type.in(ID($memwr), ID($memwr_v2))) {
+ bool is_compat = cell->type == ID($memwr);
+ IdString memid = cell->parameters.at(ID::MEMID).decode_string();
+ int port_id = cell->parameters.at(is_compat ? ID::PRIORITY : ID::PORTID).as_int();
+ if (port_id >= next_port_id[memid])
+ next_port_id[memid] = port_id + 1;
+ }
+ }
+ for (auto &proc_it : module->processes)
+ if (design->selected(module, proc_it.second))
+ proc_memwr(module, proc_it.second, next_port_id);
+ }
+ }
+} ProcMemWrPass;
+
+PRIVATE_NAMESPACE_END
+
diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc
index d20f34534..b209057fe 100644
--- a/passes/proc/proc_mux.cc
+++ b/passes/proc/proc_mux.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/proc/proc_prune.cc b/passes/proc/proc_prune.cc
index bd122b91f..9f1080ef6 100644
--- a/passes/proc/proc_prune.cc
+++ b/passes/proc/proc_prune.cc
@@ -67,51 +67,36 @@ struct PruneWorker
}
for (auto it = cs->actions.rbegin(); it != cs->actions.rend(); ) {
RTLIL::SigSpec lhs = sigmap(it->first);
- bool redundant = true;
- for (auto &bit : lhs) {
+ RTLIL::SigSpec rhs = sigmap(it->second);
+ SigSpec new_lhs, new_rhs;
+ SigSpec conn_lhs, conn_rhs;
+ for (int i = 0; i < GetSize(lhs); i++) {
+ SigBit bit = lhs[i];
if (bit.wire && !assigned[bit]) {
- redundant = false;
- break;
- }
- }
- bool remove = false;
- if (redundant) {
- removed_count++;
- remove = true;
- } else {
- if (root) {
- bool promotable = true;
- for (auto &bit : lhs) {
- if (bit.wire && affected[bit] && !assigned[bit]) {
- promotable = false;
- break;
- }
- }
- if (promotable) {
- RTLIL::SigSpec rhs = sigmap(it->second);
- RTLIL::SigSig conn;
- for (int i = 0; i < GetSize(lhs); i++) {
- RTLIL::SigBit lhs_bit = lhs[i];
- if (lhs_bit.wire && !assigned[lhs_bit]) {
- conn.first.append(lhs_bit);
- conn.second.append(rhs.extract(i));
- }
- }
- promoted_count++;
- module->connect(conn);
- remove = true;
+ if (!affected[bit] && root) {
+ conn_lhs.append(bit);
+ conn_rhs.append(rhs[i]);
+ } else {
+ new_lhs.append(bit);
+ new_rhs.append(rhs[i]);
}
+ assigned.insert(bit);
+ affected.insert(bit);
}
- for (auto &bit : lhs)
- if (bit.wire)
- assigned.insert(bit);
- for (auto &bit : lhs)
- if (bit.wire)
- affected.insert(bit);
}
- if (remove)
+ if (GetSize(conn_lhs)) {
+ promoted_count++;
+ module->connect(conn_lhs, conn_rhs);
+ }
+ if (GetSize(new_lhs) == 0) {
+ if (GetSize(conn_lhs) == 0)
+ removed_count++;
cs->actions.erase((it++).base() - 1);
- else it++;
+ } else {
+ it->first = new_lhs;
+ it->second = new_rhs;
+ it++;
+ }
}
return assigned;
}
diff --git a/passes/proc/proc_rmdead.cc b/passes/proc/proc_rmdead.cc
index ee91637ca..2ec11415a 100644
--- a/passes/proc/proc_rmdead.cc
+++ b/passes/proc/proc_rmdead.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -28,9 +28,62 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-void proc_rmdead(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter)
+static bool can_use_fully_defined_pool(RTLIL::SwitchRule *sw)
+{
+ if (!GetSize(sw->signal))
+ return false;
+
+ for (const RTLIL::SigBit &bit : sw->signal)
+ if (bit.wire == NULL)
+ return false;
+
+ for (const RTLIL::CaseRule *cas : sw->cases)
+ for (const RTLIL::SigSpec &sig : cas->compare)
+ if (!sig.is_fully_def())
+ return false;
+
+ return true;
+}
+
+// This replicates the necessary parts of BitPatternPool's interface, but rather
+// than storing remaining patterns, this explicitly stores which fully-defined
+// constants have already been matched.
+struct FullyDefinedPool
+{
+ FullyDefinedPool(const RTLIL::SigSpec &signal)
+ : max_patterns{signal.size() >= 32 ? 0ul : 1ul << signal.size()}
+ {}
+
+ bool take(RTLIL::SigSpec sig)
+ {
+ if (default_reached || patterns.count(sig))
+ return false;
+ patterns.insert(sig);
+ return true;
+ }
+
+ void take_all()
+ {
+ default_reached = true;
+ }
+
+ bool empty()
+ {
+ return default_reached ||
+ (max_patterns && max_patterns == patterns.size());
+ }
+
+ pool<RTLIL::SigSpec> patterns;
+ bool default_reached = false;
+ size_t max_patterns;
+};
+
+void proc_rmdead(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter);
+
+template <class Pool>
+static void proc_rmdead_impl(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter)
{
- BitPatternPool pool(sw->signal);
+ Pool pool(sw->signal);
for (size_t i = 0; i < sw->cases.size(); i++)
{
@@ -68,6 +121,14 @@ void proc_rmdead(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter)
}
}
+void proc_rmdead(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter)
+{
+ if (can_use_fully_defined_pool(sw))
+ proc_rmdead_impl<FullyDefinedPool>(sw, counter, full_case_counter);
+ else
+ proc_rmdead_impl<BitPatternPool>(sw, counter, full_case_counter);
+}
+
struct ProcRmdeadPass : public Pass {
ProcRmdeadPass() : Pass("proc_rmdead", "eliminate dead trees in decision trees") { }
void help() override
diff --git a/passes/sat/assertpmux.cc b/passes/sat/assertpmux.cc
index f31b78804..abdcb2240 100644
--- a/passes/sat/assertpmux.cc
+++ b/passes/sat/assertpmux.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc
index 3fa5a614c..46c76eba9 100644
--- a/passes/sat/async2sync.cc
+++ b/passes/sat/async2sync.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -41,8 +41,6 @@ struct Async2syncPass : public Pass {
log("reset value in the next cycle regardless of the data-in value at the time of\n");
log("the clock edge.\n");
log("\n");
- log("Currently only $adff, $dffsr, and $dlatch cells are supported by this pass.\n");
- log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
@@ -74,16 +72,13 @@ struct Async2syncPass : public Pass {
FfData ff(&initvals, cell);
// Skip for $_FF_ and $ff cells.
- if (ff.has_d && !ff.has_clk && !ff.has_en)
+ if (ff.has_gclk)
continue;
if (ff.has_clk)
{
- if (!ff.has_sr && !ff.has_arst)
- continue;
-
if (ff.has_sr) {
- ff.unmap_ce_srst(module);
+ ff.unmap_ce_srst();
log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%s, Q=%s\n",
log_id(module), log_id(cell), log_id(cell->type),
@@ -128,8 +123,41 @@ struct Async2syncPass : public Pass {
ff.sig_d = new_d;
ff.sig_q = new_q;
ff.has_sr = false;
+ } else if (ff.has_aload) {
+ ff.unmap_ce_srst();
+
+ log("Replacing %s.%s (%s): ALOAD=%s, AD=%s, D=%s, Q=%s\n",
+ log_id(module), log_id(cell), log_id(cell->type),
+ log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_d), log_signal(ff.sig_q));
+
+ initvals.remove_init(ff.sig_q);
+
+ Wire *new_d = module->addWire(NEW_ID, ff.width);
+ Wire *new_q = module->addWire(NEW_ID, ff.width);
+
+ if (ff.pol_aload) {
+ if (!ff.is_fine) {
+ module->addMux(NEW_ID, new_q, ff.sig_ad, ff.sig_aload, ff.sig_q);
+ module->addMux(NEW_ID, ff.sig_d, ff.sig_ad, ff.sig_aload, new_d);
+ } else {
+ module->addMuxGate(NEW_ID, new_q, ff.sig_ad, ff.sig_aload, ff.sig_q);
+ module->addMuxGate(NEW_ID, ff.sig_d, ff.sig_ad, ff.sig_aload, new_d);
+ }
+ } else {
+ if (!ff.is_fine) {
+ module->addMux(NEW_ID, ff.sig_ad, new_q, ff.sig_aload, ff.sig_q);
+ module->addMux(NEW_ID, ff.sig_ad, ff.sig_d, ff.sig_aload, new_d);
+ } else {
+ module->addMuxGate(NEW_ID, ff.sig_ad, new_q, ff.sig_aload, ff.sig_q);
+ module->addMuxGate(NEW_ID, ff.sig_ad, ff.sig_d, ff.sig_aload, new_d);
+ }
+ }
+
+ ff.sig_d = new_d;
+ ff.sig_q = new_q;
+ ff.has_aload = false;
} else if (ff.has_arst) {
- ff.unmap_srst(module);
+ ff.unmap_srst();
log("Replacing %s.%s (%s): ARST=%s, D=%s, Q=%s\n",
log_id(module), log_id(cell), log_id(cell->type),
@@ -154,9 +182,12 @@ struct Async2syncPass : public Pass {
ff.sig_q = new_q;
ff.has_arst = false;
ff.has_srst = true;
+ ff.ce_over_srst = false;
ff.val_srst = ff.val_arst;
ff.sig_srst = ff.sig_arst;
ff.pol_srst = ff.pol_arst;
+ } else {
+ continue;
}
}
else
@@ -164,25 +195,25 @@ struct Async2syncPass : public Pass {
// Latch.
log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n",
log_id(module), log_id(cell), log_id(cell->type),
- log_signal(ff.sig_en), log_signal(ff.sig_d), log_signal(ff.sig_q));
+ log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_q));
initvals.remove_init(ff.sig_q);
Wire *new_q = module->addWire(NEW_ID, ff.width);
Wire *new_d;
- if (ff.has_d) {
+ if (ff.has_aload) {
new_d = module->addWire(NEW_ID, ff.width);
- if (ff.pol_en) {
+ if (ff.pol_aload) {
if (!ff.is_fine)
- module->addMux(NEW_ID, new_q, ff.sig_d, ff.sig_en, new_d);
+ module->addMux(NEW_ID, new_q, ff.sig_ad, ff.sig_aload, new_d);
else
- module->addMuxGate(NEW_ID, new_q, ff.sig_d, ff.sig_en, new_d);
+ module->addMuxGate(NEW_ID, new_q, ff.sig_ad, ff.sig_aload, new_d);
} else {
if (!ff.is_fine)
- module->addMux(NEW_ID, ff.sig_d, new_q, ff.sig_en, new_d);
+ module->addMux(NEW_ID, ff.sig_ad, new_q, ff.sig_aload, new_d);
else
- module->addMuxGate(NEW_ID, ff.sig_d, new_q, ff.sig_en, new_d);
+ module->addMuxGate(NEW_ID, ff.sig_ad, new_q, ff.sig_aload, new_d);
}
} else {
new_d = new_q;
@@ -231,15 +262,12 @@ struct Async2syncPass : public Pass {
ff.sig_d = new_d;
ff.sig_q = new_q;
- ff.has_en = false;
+ ff.has_aload = false;
ff.has_arst = false;
ff.has_sr = false;
- ff.has_d = true;
+ ff.has_gclk = true;
}
-
- IdString name = cell->name;
- module->remove(cell);
- ff.emit(module, name);
+ ff.emit();
}
}
}
diff --git a/passes/sat/clk2fflogic.cc b/passes/sat/clk2fflogic.cc
index b9ba5ee3c..f37e07a89 100644
--- a/passes/sat/clk2fflogic.cc
+++ b/passes/sat/clk2fflogic.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -151,18 +151,36 @@ struct Clk2fflogicPass : public Pass {
if (RTLIL::builtin_ff_cell_types().count(cell->type)) {
FfData ff(&initvals, cell);
- if (ff.has_d && !ff.has_clk && !ff.has_en) {
+ if (ff.has_gclk) {
// Already a $ff or $_FF_ cell.
continue;
}
+ if (ff.has_clk) {
+ log("Replacing %s.%s (%s): CLK=%s, D=%s, Q=%s\n",
+ log_id(module), log_id(cell), log_id(cell->type),
+ log_signal(ff.sig_clk), log_signal(ff.sig_d), log_signal(ff.sig_q));
+ } else if (ff.has_aload) {
+ log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n",
+ log_id(module), log_id(cell), log_id(cell->type),
+ log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_q));
+ } else {
+ // $sr.
+ log("Replacing %s.%s (%s): SET=%s, CLR=%s, Q=%s\n",
+ log_id(module), log_id(cell), log_id(cell->type),
+ log_signal(ff.sig_set), log_signal(ff.sig_clr), log_signal(ff.sig_q));
+ }
+
+ ff.remove();
+
// Strip spaces from signal name, since Yosys IDs can't contain spaces
- // Spaces only occur when have a signal that's a slice of a larger bus,
+ // Spaces only occur when we have a signal that's a slice of a larger bus,
// e.g. "\myreg [5:0]", so removing spaces shouldn't result in loss of uniqueness
std::string sig_q_str = log_signal(ff.sig_q);
sig_q_str.erase(std::remove(sig_q_str.begin(), sig_q_str.end(), ' '), sig_q_str.end());
Wire *past_q = module->addWire(NEW_ID_SUFFIX(stringf("%s#past_q_wire", sig_q_str.c_str())), ff.width);
+
if (!ff.is_fine) {
module->addFf(NEW_ID, ff.sig_q, past_q);
} else {
@@ -172,7 +190,7 @@ struct Clk2fflogicPass : public Pass {
initvals.set_init(past_q, ff.val_init);
if (ff.has_clk) {
- ff.unmap_ce_srst(module);
+ ff.unmap_ce_srst();
Wire *past_clk = module->addWire(NEW_ID_SUFFIX(stringf("%s#past_clk#%s", sig_q_str.c_str(), log_signal(ff.sig_clk))));
initvals.set_init(past_clk, ff.pol_clk ? State::S1 : State::S0);
@@ -182,10 +200,6 @@ struct Clk2fflogicPass : public Pass {
else
module->addFfGate(NEW_ID, ff.sig_clk, past_clk);
- log("Replacing %s.%s (%s): CLK=%s, D=%s, Q=%s\n",
- log_id(module), log_id(cell), log_id(cell->type),
- log_signal(ff.sig_clk), log_signal(ff.sig_d), log_signal(ff.sig_q));
-
SigSpec clock_edge_pattern;
if (ff.pol_clk) {
@@ -211,25 +225,17 @@ struct Clk2fflogicPass : public Pass {
qval = module->Mux(NEW_ID, past_q, past_d, clock_edge);
else
qval = module->MuxGate(NEW_ID, past_q, past_d, clock_edge);
- } else if (ff.has_d) {
-
- log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n",
- log_id(module), log_id(cell), log_id(cell->type),
- log_signal(ff.sig_en), log_signal(ff.sig_d), log_signal(ff.sig_q));
+ } else {
+ qval = past_q;
+ }
- SigSpec sig_en = wrap_async_control(module, ff.sig_en, ff.pol_en);
+ if (ff.has_aload) {
+ SigSpec sig_aload = wrap_async_control(module, ff.sig_aload, ff.pol_aload);
if (!ff.is_fine)
- qval = module->Mux(NEW_ID, past_q, ff.sig_d, sig_en);
+ qval = module->Mux(NEW_ID, qval, ff.sig_ad, sig_aload);
else
- qval = module->MuxGate(NEW_ID, past_q, ff.sig_d, sig_en);
- } else {
-
- log("Replacing %s.%s (%s): SET=%s, CLR=%s, Q=%s\n",
- log_id(module), log_id(cell), log_id(cell->type),
- log_signal(ff.sig_set), log_signal(ff.sig_clr), log_signal(ff.sig_q));
-
- qval = past_q;
+ qval = module->MuxGate(NEW_ID, qval, ff.sig_ad, sig_aload);
}
if (ff.has_sr) {
@@ -254,10 +260,6 @@ struct Clk2fflogicPass : public Pass {
} else {
module->connect(ff.sig_q, qval);
}
-
- initvals.remove_init(ff.sig_q);
- module->remove(cell);
- continue;
}
}
}
diff --git a/passes/sat/cutpoint.cc b/passes/sat/cutpoint.cc
index 6fc267d51..bca6a5ec6 100644
--- a/passes/sat/cutpoint.cc
+++ b/passes/sat/cutpoint.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/sat/eval.cc b/passes/sat/eval.cc
index 085e7c5b8..05879426e 100644
--- a/passes/sat/eval.cc
+++ b/passes/sat/eval.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -18,7 +18,7 @@
*/
// [[CITE]] VlogHammer Verilog Regression Test Suite
-// http://www.clifford.at/yosys/vloghammer.html
+// https://yosyshq.net/yosys/vloghammer.html
#include "kernel/register.h"
#include "kernel/celltypes.h"
diff --git a/passes/sat/expose.cc b/passes/sat/expose.cc
index 2c65821cf..e7ec29ee4 100644
--- a/passes/sat/expose.cc
+++ b/passes/sat/expose.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/sat/fmcombine.cc b/passes/sat/fmcombine.cc
index cb49edac3..e15bdf6a8 100644
--- a/passes/sat/fmcombine.cc
+++ b/passes/sat/fmcombine.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/sat/fminit.cc b/passes/sat/fminit.cc
index c72e62548..5f4ec0068 100644
--- a/passes/sat/fminit.cc
+++ b/passes/sat/fminit.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/sat/freduce.cc b/passes/sat/freduce.cc
index f87b85da9..52e80f667 100644
--- a/passes/sat/freduce.cc
+++ b/passes/sat/freduce.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/sat/miter.cc b/passes/sat/miter.cc
index fe4a819f3..37efadfbd 100644
--- a/passes/sat/miter.cc
+++ b/passes/sat/miter.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/sat/mutate.cc b/passes/sat/mutate.cc
index 95e0e0944..42eb0c6d0 100644
--- a/passes/sat/mutate.cc
+++ b/passes/sat/mutate.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc
index 9fdac6147..df2725b3c 100644
--- a/passes/sat/sat.cc
+++ b/passes/sat/sat.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc
index 3ba66bd33..a7c109374 100644
--- a/passes/sat/sim.cc
+++ b/passes/sat/sim.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -21,12 +21,49 @@
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
#include "kernel/mem.h"
+#include "kernel/fstdata.h"
#include <ctime>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
+enum class SimulationMode {
+ sim,
+ cmp,
+ gold,
+ gate,
+};
+
+static const std::map<std::string, int> g_units =
+{
+ { "", -9 }, // default is ns
+ { "s", 0 },
+ { "ms", -3 },
+ { "us", -6 },
+ { "ns", -9 },
+ { "ps", -12 },
+ { "fs", -15 },
+ { "as", -18 },
+ { "zs", -21 },
+};
+
+static double stringToTime(std::string str)
+{
+ if (str=="END") return -1;
+
+ char *endptr;
+ long value = strtol(str.c_str(), &endptr, 10);
+
+ if (g_units.find(endptr)==g_units.end())
+ log_error("Cannot parse '%s', bad unit '%s'\n", str.c_str(), endptr);
+
+ if (value < 0)
+ log_error("Time value '%s' must be positive\n", str.c_str());
+
+ return value * pow(10.0, g_units.at(endptr));
+}
+
struct SimShared
{
bool debug = false;
@@ -34,6 +71,11 @@ struct SimShared
bool writeback = false;
bool zinit = false;
int rstlen = 1;
+ FstData *fst = nullptr;
+ double start_time = 0;
+ double stop_time = -1;
+ SimulationMode sim_mode = SimulationMode::sim;
+ bool cycles_set = false;
};
void zinit(State &v)
@@ -51,7 +93,8 @@ void zinit(Const &v)
struct SimInstance
{
SimShared *shared;
-
+
+ std::string scope;
Module *module;
Cell *instance;
@@ -92,9 +135,11 @@ struct SimInstance
std::vector<Mem> memories;
dict<Wire*, pair<int, Const>> vcd_database;
+ dict<Wire*, pair<fstHandle, Const>> fst_database;
+ dict<Wire*, fstHandle> fst_handles;
- SimInstance(SimShared *shared, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) :
- shared(shared), module(module), instance(instance), parent(parent), sigmap(module)
+ SimInstance(SimShared *shared, std::string scope, Module *module, Cell *instance = nullptr, SimInstance *parent = nullptr) :
+ shared(shared), scope(scope), module(module), instance(instance), parent(parent), sigmap(module)
{
log_assert(module);
@@ -116,6 +161,13 @@ struct SimInstance
}
}
+ if ((shared->fst) && !(shared->hide_internal && wire->name[0] == '$')) {
+ fstHandle id = shared->fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name));
+ if (id==0 && wire->name.isPublic())
+ log_warning("Unable to found wire %s in input file.\n", (scope + "." + RTLIL::unescape_id(wire->name)).c_str());
+ fst_handles[wire] = id;
+ }
+
if (wire->attributes.count(ID::init)) {
Const initval = wire->attributes.at(ID::init);
for (int i = 0; i < GetSize(sig) && i < GetSize(initval); i++)
@@ -144,7 +196,7 @@ struct SimInstance
Module *mod = module->design->module(cell->type);
if (mod != nullptr) {
- dirty_children.insert(new SimInstance(shared, mod, cell, this));
+ dirty_children.insert(new SimInstance(shared, scope + "." + RTLIL::unescape_id(cell->name), mod, cell, this));
}
for (auto &port : cell->connections()) {
@@ -164,7 +216,7 @@ struct SimInstance
ff_database[cell] = ff;
}
- if (cell->type.in(ID($mem), ID($meminit), ID($memwr), ID($memrd)))
+ if (cell->is_mem_cell())
{
mem_cells[cell] = cell->parameters.at(ID::MEMID).decode_string();
}
@@ -271,7 +323,7 @@ struct SimInstance
{
auto child = children.at(cell);
for (auto &conn: cell->connections())
- if (cell->input(conn.first)) {
+ if (cell->input(conn.first) && GetSize(conn.second)) {
Const value = get_state(conn.second);
child->set_state(child->module->wire(conn.first), value);
}
@@ -313,6 +365,12 @@ struct SimInstance
return;
}
+ // (A,S -> Y) cells
+ if (has_a && !has_b && !has_c && !has_d && has_s && has_y) {
+ set_state(sig_y, CellTypes::eval(cell, get_state(sig_a), get_state(sig_s)));
+ return;
+ }
+
// (A,B,S -> Y) cells
if (has_a && has_b && !has_c && !has_d && has_s && has_y) {
set_state(sig_y, CellTypes::eval(cell, get_state(sig_a), get_state(sig_b), get_state(sig_s)));
@@ -334,7 +392,7 @@ struct SimInstance
{
auto &port = mem.rd_ports[port_idx];
Const addr = get_state(port.addr);
- Const data = Const(State::Sx, mem.width);
+ Const data = Const(State::Sx, mem.width << port.wide_log2);
if (port.clk_enable)
log_error("Memory %s.%s has clocked read ports. Run 'memory' with -nordff.\n", log_id(module), log_id(mem.memid));
@@ -342,7 +400,7 @@ struct SimInstance
if (addr.is_fully_def()) {
int index = addr.as_int() - mem.start_offset;
if (index >= 0 && index < mem.size)
- data = mdb.data.extract(index*mem.width, mem.width);
+ data = mdb.data.extract(index*mem.width, mem.width << port.wide_log2);
}
set_state(port.data, data);
@@ -457,7 +515,7 @@ struct SimInstance
{
int index = addr.as_int() - mem.start_offset;
if (index >= 0 && index < mem.size)
- for (int i = 0; i < mem.width; i++)
+ for (int i = 0; i < (mem.width << port.wide_log2); i++)
if (enable[i] == State::S1 && mdb.data.bits.at(index*mem.width+i) != data[i]) {
mdb.data.bits.at(index*mem.width+i) = data[i];
dirty_memories.insert(mem.memid);
@@ -559,6 +617,7 @@ struct SimInstance
MemInit minit;
minit.addr = mem.mem->start_offset;
minit.data = mem.data;
+ minit.en = Const(State::S1, mem.mem->width);
mem.mem->inits.push_back(minit);
mem.mem->emit();
}
@@ -615,14 +674,125 @@ struct SimInstance
for (auto child : children)
child.second->write_vcd_step(f);
}
+
+ void write_fst_header(struct fstContext *f)
+ {
+ fstWriterSetScope(f, FST_ST_VCD_MODULE, stringf("%s",log_id(name())).c_str(), nullptr);
+ for (auto wire : module->wires())
+ {
+ if (shared->hide_internal && wire->name[0] == '$')
+ continue;
+
+ fstHandle id = fstWriterCreateVar(f, FST_VT_VCD_WIRE, FST_VD_IMPLICIT, GetSize(wire),
+ stringf("%s%s", wire->name[0] == '$' ? "\\" : "", log_id(wire)).c_str(), 0);
+ fst_database[wire] = make_pair(id, Const());
+ }
+
+ for (auto child : children)
+ child.second->write_fst_header(f);
+
+ fstWriterSetUpscope(f);
+ }
+
+ void write_fst_step(struct fstContext *f)
+ {
+ for (auto &it : fst_database)
+ {
+ Wire *wire = it.first;
+ Const value = get_state(wire);
+ fstHandle id = it.second.first;
+
+ if (it.second.second == value)
+ continue;
+
+ it.second.second = value;
+ std::stringstream ss;
+ for (int i = GetSize(value)-1; i >= 0; i--) {
+ switch (value[i]) {
+ case State::S0: ss << "0"; break;
+ case State::S1: ss << "1"; break;
+ case State::Sx: ss << "x"; break;
+ default: ss << "z";
+ }
+ }
+ fstWriterEmitValueChange(f, id, ss.str().c_str());
+ }
+
+ for (auto child : children)
+ child.second->write_fst_step(f);
+ }
+
+ void setInitState(uint64_t time)
+ {
+ for (auto &it : ff_database)
+ {
+ Cell *cell = it.first;
+
+ SigSpec qsig = cell->getPort(ID::Q);
+ if (qsig.is_wire()) {
+ IdString name = qsig.as_wire()->name;
+ fstHandle id = shared->fst->getHandle(scope + "." + RTLIL::unescape_id(name));
+ if (id==0 && name.isPublic())
+ log_warning("Unable to found wire %s in input file.\n", (scope + "." + RTLIL::unescape_id(name)).c_str());
+ if (id!=0) {
+ Const fst_val = Const::from_string(shared->fst->valueAt(id, time));
+ set_state(qsig, fst_val);
+ }
+ }
+ }
+ for (auto child : children)
+ child.second->setInitState(time);
+ }
+
+ bool checkSignals(uint64_t time)
+ {
+ bool retVal = false;
+ for(auto &item : fst_handles) {
+ if (item.second==0) continue; // Ignore signals not found
+ Const fst_val = Const::from_string(shared->fst->valueAt(item.second, time));
+ Const sim_val = get_state(item.first);
+ if (sim_val.size()!=fst_val.size())
+ log_error("Signal '%s' size is different in gold and gate.\n", log_id(item.first));
+ if (shared->sim_mode == SimulationMode::sim) {
+ // No checks performed when using stimulus
+ } else if (shared->sim_mode == SimulationMode::gate && !fst_val.is_fully_def()) { // FST data contains X
+ for(int i=0;i<fst_val.size();i++) {
+ if (fst_val[i]!=State::Sx && fst_val[i]!=sim_val[i]) {
+ log_warning("Signal '%s' in file %s in simulation %s\n", log_id(item.first), log_signal(fst_val), log_signal(sim_val));
+ retVal = true;
+ break;
+ }
+ }
+ } else if (shared->sim_mode == SimulationMode::gold && !sim_val.is_fully_def()) { // sim data contains X
+ for(int i=0;i<sim_val.size();i++) {
+ if (sim_val[i]!=State::Sx && fst_val[i]!=sim_val[i]) {
+ log_warning("Signal '%s' in file %s in simulation %s\n", log_id(item.first), log_signal(fst_val), log_signal(sim_val));
+ retVal = true;
+ break;
+ }
+ }
+ } else {
+ if (fst_val!=sim_val) {
+ log_warning("Signal '%s' in file %s in simulation '%s'\n", log_id(item.first), log_signal(fst_val), log_signal(sim_val));
+ retVal = true;
+ }
+ }
+ }
+ for (auto child : children)
+ retVal |= child.second->checkSignals(time);
+ return retVal;
+ }
};
struct SimWorker : SimShared
{
SimInstance *top = nullptr;
std::ofstream vcdfile;
+ struct fstContext *fstfile = nullptr;
pool<IdString> clock, clockn, reset, resetn;
std::string timescale;
+ std::string sim_filename;
+ std::string scope;
~SimWorker()
{
@@ -631,9 +801,6 @@ struct SimWorker : SimShared
void write_vcd_header()
{
- if (!vcdfile.is_open())
- return;
-
vcdfile << stringf("$version %s $end\n", yosys_version_str);
std::time_t t = std::time(nullptr);
@@ -653,13 +820,53 @@ struct SimWorker : SimShared
void write_vcd_step(int t)
{
- if (!vcdfile.is_open())
- return;
-
vcdfile << stringf("#%d\n", t);
top->write_vcd_step(vcdfile);
}
+ void write_fst_header()
+ {
+ std::time_t t = std::time(nullptr);
+ fstWriterSetDate(fstfile, asctime(std::localtime(&t)));
+ fstWriterSetVersion(fstfile, yosys_version_str);
+ if (!timescale.empty())
+ fstWriterSetTimescaleFromString(fstfile, timescale.c_str());
+
+ fstWriterSetPackType(fstfile, FST_WR_PT_FASTLZ);
+ fstWriterSetRepackOnClose(fstfile, 1);
+
+ top->write_fst_header(fstfile);
+ }
+
+ void write_fst_step(int t)
+ {
+ fstWriterEmitTimeChange(fstfile, t);
+
+ top->write_fst_step(fstfile);
+ }
+
+ void write_output_header()
+ {
+ if (vcdfile.is_open())
+ write_vcd_header();
+ if (fstfile)
+ write_fst_header();
+ }
+
+ void write_output_step(int t)
+ {
+ if (vcdfile.is_open())
+ write_vcd_step(t);
+ if (fstfile)
+ write_fst_step(t);
+ }
+
+ void write_output_end()
+ {
+ if (fstfile)
+ fstWriterClose(fstfile);
+ }
+
void update()
{
while (1)
@@ -698,7 +905,7 @@ struct SimWorker : SimShared
void run(Module *topmod, int numcycles)
{
log_assert(top == nullptr);
- top = new SimInstance(this, topmod);
+ top = new SimInstance(this, scope, topmod);
if (debug)
log("\n===== 0 =====\n");
@@ -713,24 +920,25 @@ struct SimWorker : SimShared
update();
- write_vcd_header();
- write_vcd_step(0);
+ write_output_header();
+ write_output_step(0);
for (int cycle = 0; cycle < numcycles; cycle++)
{
if (debug)
log("\n===== %d =====\n", 10*cycle + 5);
-
+ else
+ log("Simulating cycle %d.\n", (cycle*2)+1);
set_inports(clock, State::S0);
set_inports(clockn, State::S1);
update();
- write_vcd_step(10*cycle + 5);
+ write_output_step(10*cycle + 5);
if (debug)
log("\n===== %d =====\n", 10*cycle + 10);
else
- log("Simulating cycle %d.\n", cycle+1);
+ log("Simulating cycle %d.\n", (cycle*2)+2);
set_inports(clock, State::S1);
set_inports(clockn, State::S0);
@@ -741,11 +949,132 @@ struct SimWorker : SimShared
}
update();
- write_vcd_step(10*cycle + 10);
+ write_output_step(10*cycle + 10);
}
- write_vcd_step(10*numcycles + 2);
+ write_output_step(10*numcycles + 2);
+
+ write_output_end();
+
+ if (writeback) {
+ pool<Module*> wbmods;
+ top->writeback(wbmods);
+ }
+ }
+
+ void run_cosim(Module *topmod, int numcycles)
+ {
+ log_assert(top == nullptr);
+ fst = new FstData(sim_filename);
+
+ if (scope.empty())
+ log_error("Scope must be defined for co-simulation.\n");
+
+ top = new SimInstance(this, scope, topmod);
+
+ std::vector<fstHandle> fst_clock;
+
+ for (auto portname : clock)
+ {
+ Wire *w = topmod->wire(portname);
+ if (!w)
+ log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module));
+ if (!w->port_input)
+ log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module));
+ fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname));
+ if (id==0)
+ log_error("Can't find port %s.%s in FST.\n", scope.c_str(), log_id(portname));
+ fst_clock.push_back(id);
+ }
+ for (auto portname : clockn)
+ {
+ Wire *w = topmod->wire(portname);
+ if (!w)
+ log_error("Can't find port %s on module %s.\n", log_id(portname), log_id(top->module));
+ if (!w->port_input)
+ log_error("Clock port %s on module %s is not input.\n", log_id(portname), log_id(top->module));
+ fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(portname));
+ if (id==0)
+ log_error("Can't find port %s.%s in FST.\n", scope.c_str(), log_id(portname));
+ fst_clock.push_back(id);
+ }
+ if (fst_clock.size()==0)
+ log_error("No clock signals defined for input file\n");
+
+ SigMap sigmap(topmod);
+ std::map<Wire*,fstHandle> inputs;
+
+ for (auto wire : topmod->wires()) {
+ if (wire->port_input) {
+ fstHandle id = fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name));
+ if (id==0)
+ log_error("Unable to find required '%s' signal in file\n",(scope + "." + RTLIL::unescape_id(wire->name)).c_str());
+ inputs[wire] = id;
+ }
+ }
+
+ uint64_t startCount = 0;
+ uint64_t stopCount = 0;
+ if (start_time==0) {
+ if (start_time < fst->getStartTime())
+ log_warning("Start time is before simulation file start time\n");
+ startCount = fst->getStartTime();
+ } else if (start_time==-1)
+ startCount = fst->getEndTime();
+ else {
+ startCount = start_time / fst->getTimescale();
+ if (startCount > fst->getEndTime()) {
+ startCount = fst->getEndTime();
+ log_warning("Start time is after simulation file end time\n");
+ }
+ }
+ if (stop_time==0) {
+ if (stop_time < fst->getStartTime())
+ log_warning("Stop time is before simulation file start time\n");
+ stopCount = fst->getStartTime();
+ } else if (stop_time==-1)
+ stopCount = fst->getEndTime();
+ else {
+ stopCount = stop_time / fst->getTimescale();
+ if (stopCount > fst->getEndTime()) {
+ stopCount = fst->getEndTime();
+ log_warning("Stop time is after simulation file end time\n");
+ }
+ }
+ if (stopCount<startCount) {
+ log_error("Stop time is before start time\n");
+ }
+ auto samples = fst->getAllEdges(fst_clock, startCount, stopCount);
+
+ // Limit to number of cycles if provided
+ if (cycles_set && ((size_t)(numcycles *2) < samples.size()))
+ samples.erase(samples.begin() + (numcycles*2), samples.end());
+
+ // Add setup time (start time)
+ if (samples.empty() || samples.front()!=startCount)
+ samples.insert(samples.begin(), startCount);
+
+ fst->reconstructAllAtTimes(samples);
+ bool initial = true;
+ int cycle = 0;
+ log("Co-simulation from %lu%s to %lu%s\n", (unsigned long)startCount, fst->getTimescaleString(), (unsigned long)stopCount, fst->getTimescaleString());
+ for(auto &time : samples) {
+ log("Co-simulating cycle %d [%lu%s].\n", cycle, (unsigned long)time, fst->getTimescaleString());
+ for(auto &item : inputs) {
+ std::string v = fst->valueAt(item.second, time);
+ top->set_state(item.first, Const::from_string(v));
+ }
+ if (initial) {
+ top->setInitState(time);
+ initial = false;
+ }
+ update();
+ bool status = top->checkSignals(time);
+ if (status)
+ log_error("Signal difference\n");
+ cycle++;
+ }
if (writeback) {
pool<Module*> wbmods;
top->writeback(wbmods);
@@ -766,6 +1095,9 @@ struct SimPass : public Pass {
log(" -vcd <filename>\n");
log(" write the simulation results to the given VCD file\n");
log("\n");
+ log(" -fst <filename>\n");
+ log(" write the simulation results to the given FST file\n");
+ log("\n");
log(" -clock <portname>\n");
log(" name of top-level clock input\n");
log("\n");
@@ -788,14 +1120,41 @@ struct SimPass : public Pass {
log(" include the specified timescale declaration in the vcd\n");
log("\n");
log(" -n <integer>\n");
- log(" number of cycles to simulate (default: 20)\n");
+ log(" number of clock cycles to simulate (default: 20)\n");
log("\n");
log(" -a\n");
- log(" include all nets in VCD output, not just those with public names\n");
+ log(" use all nets in VCD/FST operations, not just those with public names\n");
log("\n");
log(" -w\n");
log(" writeback mode: use final simulation state as new init state\n");
log("\n");
+ log(" -r\n");
+ log(" read simulation results file (file formats supported: FST)\n");
+ log("\n");
+ log(" -scope\n");
+ log(" scope of simulation top model\n");
+ log("\n");
+ log(" -at <time>\n");
+ log(" sets start and stop time\n");
+ log("\n");
+ log(" -start <time>\n");
+ log(" start co-simulation in arbitary time (default 0)\n");
+ log("\n");
+ log(" -stop <time>\n");
+ log(" stop co-simulation in arbitary time (default END)\n");
+ log("\n");
+ log(" -sim\n");
+ log(" simulation with stimulus from FST (default)\n");
+ log("\n");
+ log(" -sim-cmp\n");
+ log(" co-simulation expect exact match\n");
+ log("\n");
+ log(" -sim-gold\n");
+ log(" co-simulation, x in simulation can match any value in FST\n");
+ log("\n");
+ log(" -sim-gate\n");
+ log(" co-simulation, x in FST can match any value in simulation\n");
+ log("\n");
log(" -d\n");
log(" enable debug output\n");
log("\n");
@@ -804,6 +1163,7 @@ struct SimPass : public Pass {
{
SimWorker worker;
int numcycles = 20;
+ bool start_set = false, stop_set = false, at_set = false;
log_header(design, "Executing SIM pass (simulate the circuit).\n");
@@ -815,8 +1175,15 @@ struct SimPass : public Pass {
worker.vcdfile.open(vcd_filename.c_str());
continue;
}
+ if (args[argidx] == "-fst" && argidx+1 < args.size()) {
+ std::string fst_filename = args[++argidx];
+ rewrite_filename(fst_filename);
+ worker.fstfile = (struct fstContext *)fstWriterCreate(fst_filename.c_str(),1);
+ continue;
+ }
if (args[argidx] == "-n" && argidx+1 < args.size()) {
numcycles = atoi(args[++argidx].c_str());
+ worker.cycles_set = true;
continue;
}
if (args[argidx] == "-rstlen" && argidx+1 < args.size()) {
@@ -859,9 +1226,55 @@ struct SimPass : public Pass {
worker.zinit = true;
continue;
}
+ if (args[argidx] == "-r" && argidx+1 < args.size()) {
+ std::string sim_filename = args[++argidx];
+ rewrite_filename(sim_filename);
+ worker.sim_filename = sim_filename;
+ continue;
+ }
+ if (args[argidx] == "-scope" && argidx+1 < args.size()) {
+ worker.scope = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-start" && argidx+1 < args.size()) {
+ worker.start_time = stringToTime(args[++argidx]);
+ start_set = true;
+ continue;
+ }
+ if (args[argidx] == "-stop" && argidx+1 < args.size()) {
+ worker.stop_time = stringToTime(args[++argidx]);
+ stop_set = true;
+ continue;
+ }
+ if (args[argidx] == "-at" && argidx+1 < args.size()) {
+ worker.start_time = stringToTime(args[++argidx]);
+ worker.stop_time = worker.start_time;
+ at_set = true;
+ continue;
+ }
+ if (args[argidx] == "-sim") {
+ worker.sim_mode = SimulationMode::sim;
+ continue;
+ }
+ if (args[argidx] == "-sim-cmp") {
+ worker.sim_mode = SimulationMode::cmp;
+ continue;
+ }
+ if (args[argidx] == "-sim-gold") {
+ worker.sim_mode = SimulationMode::gold;
+ continue;
+ }
+ if (args[argidx] == "-sim-gate") {
+ worker.sim_mode = SimulationMode::gate;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
+ if (at_set && (start_set || stop_set || worker.cycles_set))
+ log_error("'at' option can only be defined separate of 'start','stop' and 'n'\n");
+ if (stop_set && worker.cycles_set)
+ log_error("'stop' and 'n' can only be used exclusively'\n");
Module *top_mod = nullptr;
@@ -877,7 +1290,10 @@ struct SimPass : public Pass {
top_mod = mods.front();
}
- worker.run(top_mod, numcycles);
+ if (worker.sim_filename.empty())
+ worker.run(top_mod, numcycles);
+ else
+ worker.run_cosim(top_mod, numcycles);
}
} SimPass;
diff --git a/passes/sat/supercover.cc b/passes/sat/supercover.cc
index aacc044fb..38dbd3cf9 100644
--- a/passes/sat/supercover.cc
+++ b/passes/sat/supercover.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index 035699603..98ccfc303 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -29,6 +29,8 @@ OBJS += passes/techmap/extract_reduce.o
OBJS += passes/techmap/alumacc.o
OBJS += passes/techmap/dffinit.o
OBJS += passes/techmap/pmuxtree.o
+OBJS += passes/techmap/bmuxmap.o
+OBJS += passes/techmap/demuxmap.o
OBJS += passes/techmap/muxcover.o
OBJS += passes/techmap/aigmap.o
OBJS += passes/techmap/tribuf.o
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index d5286f4e9..80c6282c4 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -655,8 +655,9 @@ struct abc_output_filter
};
void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
- std::vector<std::string> &liberty_files, std::string constr_file, bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
- bool keepff, std::string delay_target, std::string sop_inputs, std::string sop_products, std::string lutin_shared, bool fast_mode,
+ std::vector<std::string> &liberty_files, std::vector<std::string> &genlib_files, std::string constr_file,
+ bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str, bool keepff, std::string delay_target,
+ std::string sop_inputs, std::string sop_products, std::string lutin_shared, bool fast_mode,
const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, bool sop_mode, bool abc_dress)
{
module = current_module;
@@ -710,8 +711,11 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
std::string abc_script = stringf("read_blif %s/input.blif; ", tempdir_name.c_str());
- if (!liberty_files.empty()) {
- for (std::string liberty_file : liberty_files) abc_script += stringf("read_lib -w %s; ", liberty_file.c_str());
+ if (!liberty_files.empty() || !genlib_files.empty()) {
+ for (std::string liberty_file : liberty_files)
+ abc_script += stringf("read_lib -w %s; ", liberty_file.c_str());
+ for (std::string liberty_file : genlib_files)
+ abc_script += stringf("read_library %s; ", liberty_file.c_str());
if (!constr_file.empty())
abc_script += stringf("read_constr -v %s; ", constr_file.c_str());
} else
@@ -739,7 +743,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT;
if (all_luts_cost_same && !fast_mode)
abc_script += "; lutpack {S}";
- } else if (!liberty_files.empty())
+ } else if (!liberty_files.empty() || !genlib_files.empty())
abc_script += constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR);
else if (sop_mode)
abc_script += fast_mode ? ABC_FAST_COMMAND_SOP : ABC_COMMAND_SOP;
@@ -1020,7 +1024,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
if (ifs.fail())
log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
- bool builtin_lib = liberty_files.empty();
+ bool builtin_lib = liberty_files.empty() && genlib_files.empty();
RTLIL::Design *mapped_design = new RTLIL::Design;
parse_blif(mapped_design, ifs, builtin_lib ? ID(DFF) : ID(_dff_), false, sop_mode);
@@ -1302,10 +1306,10 @@ struct AbcPass : public Pass {
log("\n");
log(" if no -script parameter is given, the following scripts are used:\n");
log("\n");
- log(" for -liberty without -constr:\n");
+ log(" for -liberty/-genlib without -constr:\n");
log("%s\n", fold_abc_cmd(ABC_COMMAND_LIB).c_str());
log("\n");
- log(" for -liberty with -constr:\n");
+ log(" for -liberty/-genlib with -constr:\n");
log("%s\n", fold_abc_cmd(ABC_COMMAND_CTR).c_str());
log("\n");
log(" for -lut/-luts (only one LUT size):\n");
@@ -1324,10 +1328,10 @@ struct AbcPass : public Pass {
log(" use different default scripts that are slightly faster (at the cost\n");
log(" of output quality):\n");
log("\n");
- log(" for -liberty without -constr:\n");
+ log(" for -liberty/-genlib without -constr:\n");
log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_LIB).c_str());
log("\n");
- log(" for -liberty with -constr:\n");
+ log(" for -liberty/-genlib with -constr:\n");
log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_CTR).c_str());
log("\n");
log(" for -lut/-luts:\n");
@@ -1343,8 +1347,13 @@ struct AbcPass : public Pass {
log(" generate netlists for the specified cell library (using the liberty\n");
log(" file format).\n");
log("\n");
+ log(" -genlib <file>\n");
+ log(" generate netlists for the specified cell library (using the SIS Genlib\n");
+ log(" file format).\n");
+ log("\n");
log(" -constr <file>\n");
- log(" pass this file with timing constraints to ABC. use with -liberty.\n");
+ log(" pass this file with timing constraints to ABC.\n");
+ log(" use with -liberty/-genlib.\n");
log("\n");
log(" a constr file contains two lines:\n");
log(" set_driving_cell <cell_name>\n");
@@ -1390,7 +1399,7 @@ struct AbcPass : public Pass {
log("\n");
// log(" -mux4, -mux8, -mux16\n");
// log(" try to extract 4-input, 8-input, and/or 16-input muxes\n");
- // log(" (ignored when used with -liberty or -lut)\n");
+ // log(" (ignored when used with -liberty/-genlib or -lut)\n");
// log("\n");
log(" -g type1,type2,...\n");
log(" Map to the specified list of gate types. Supported gates types are:\n");
@@ -1446,7 +1455,7 @@ struct AbcPass : public Pass {
log(" preserve naming by an equivalence check between the original and post-ABC\n");
log(" netlists (experimental).\n");
log("\n");
- log("When neither -liberty nor -lut is used, the Yosys standard cell library is\n");
+ log("When no target cell library is specified the Yosys standard cell library is\n");
log("loaded into ABC before the ABC script is executed.\n");
log("\n");
log("Note that this is a logic optimization pass within Yosys that is calling ABC\n");
@@ -1473,7 +1482,7 @@ struct AbcPass : public Pass {
std::string exe_file = yosys_abc_executable;
std::string script_file, default_liberty_file, constr_file, clk_str;
- std::vector<std::string> liberty_files;
+ std::vector<std::string> liberty_files, genlib_files;
std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1";
bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
bool show_tempdir = false, sop_mode = false;
@@ -1556,6 +1565,10 @@ struct AbcPass : public Pass {
liberty_files.push_back(args[++argidx]);
continue;
}
+ if (arg == "-genlib" && argidx+1 < args.size()) {
+ genlib_files.push_back(args[++argidx]);
+ continue;
+ }
if (arg == "-constr" && argidx+1 < args.size()) {
constr_file = args[++argidx];
continue;
@@ -1645,7 +1658,8 @@ struct AbcPass : public Pass {
}
extra_args(args, argidx, design);
- if (liberty_files.empty() && !default_liberty_file.empty()) liberty_files.push_back(default_liberty_file);
+ if (genlib_files.empty() && liberty_files.empty() && !default_liberty_file.empty())
+ liberty_files.push_back(default_liberty_file);
rewrite_filename(script_file);
if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+')
@@ -1655,6 +1669,11 @@ struct AbcPass : public Pass {
if (!liberty_files[i].empty() && !is_absolute_path(liberty_files[i]))
liberty_files[i] = std::string(pwd) + "/" + liberty_files[i];
}
+ for (int i = 0; i < GetSize(genlib_files); i++) {
+ rewrite_filename(genlib_files[i]);
+ if (!genlib_files[i].empty() && !is_absolute_path(genlib_files[i]))
+ genlib_files[i] = std::string(pwd) + "/" + genlib_files[i];
+ }
rewrite_filename(constr_file);
if (!constr_file.empty() && !is_absolute_path(constr_file))
constr_file = std::string(pwd) + "/" + constr_file;
@@ -1818,10 +1837,10 @@ struct AbcPass : public Pass {
}
}
- if (!lut_costs.empty() && !liberty_files.empty())
- log_cmd_error("Got -lut and -liberty! These two options are exclusive.\n");
- if (!constr_file.empty() && liberty_files.empty())
- log_cmd_error("Got -constr but no -liberty!\n");
+ if (!lut_costs.empty() && !(liberty_files.empty() && genlib_files.empty()))
+ log_cmd_error("Got -lut and -liberty/-genlib! These two options are exclusive.\n");
+ if (!constr_file.empty() && (liberty_files.empty() && genlib_files.empty()))
+ log_cmd_error("Got -constr but no -liberty/-genlib!\n");
if (enabled_gates.empty()) {
enabled_gates.insert("AND");
@@ -1851,7 +1870,7 @@ struct AbcPass : public Pass {
initvals.set(&assign_map, mod);
if (!dff_mode || !clk_str.empty()) {
- abc_module(design, mod, script_file, exe_file, liberty_files, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
+ abc_module(design, mod, script_file, exe_file, liberty_files, genlib_files, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, mod->selected_cells(), show_tempdir, sop_mode, abc_dress);
continue;
}
@@ -1996,7 +2015,7 @@ struct AbcPass : public Pass {
clk_sig = assign_map(std::get<1>(it.first));
en_polarity = std::get<2>(it.first);
en_sig = assign_map(std::get<3>(it.first));
- abc_module(design, mod, script_file, exe_file, liberty_files, constr_file, cleanup, lut_costs, !clk_sig.empty(), "$",
+ abc_module(design, mod, script_file, exe_file, liberty_files, genlib_files, constr_file, cleanup, lut_costs, !clk_sig.empty(), "$",
keepff, delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode, abc_dress);
assign_map.set(mod);
}
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index 56bb15495..1f00fc3e7 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* (C) 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -283,9 +283,16 @@ struct Abc9Pass : public ScriptPass
if (check_label("map")) {
if (help_mode)
- run("abc9_ops -prep_hier -prep_bypass [-prep_dff -dff]", "(option if -dff)");
+ run("abc9_ops -prep_hier [-dff]", "(option if -dff)");
else
- run(stringf("abc9_ops -prep_hier -prep_bypass %s", dff_mode ? "-prep_dff -dff" : ""));
+ run(stringf("abc9_ops -prep_hier %s", dff_mode ? "-dff" : ""));
+ run("scc -specify -set_attr abc9_scc_id {}");
+ if (help_mode)
+ run("abc9_ops -prep_bypass [-prep_dff]", "(option if -dff)");
+ else {
+ active_design->scratchpad_unset("abc9_ops.prep_bypass.did_something");
+ run(stringf("abc9_ops -prep_bypass %s", dff_mode ? "-prep_dff" : ""));
+ }
if (dff_mode) {
run("design -copy-to $abc9_map @$abc9_flops", "(only if -dff)");
run("select -unset $abc9_flops", " (only if -dff)");
@@ -330,20 +337,20 @@ struct Abc9Pass : public ScriptPass
run("design -stash $abc9_map");
run("design -load $abc9");
run("design -delete $abc9");
+ // Insert bypass modules (and perform +/abc9_map.v transformations), except for those cells part of a SCC
if (help_mode)
run("techmap -wb -max_iter 1 -map %$abc9_map -map +/abc9_map.v [-D DFF]", "(option if -dff)");
else
- run(stringf("techmap -wb -max_iter 1 -map %%$abc9_map -map +/abc9_map.v %s", dff_mode ? "-D DFF" : ""));
+ run(stringf("techmap -wb -max_iter 1 -map %%$abc9_map -map +/abc9_map.v %s a:abc9_scc_id %%n", dff_mode ? "-D DFF" : ""));
run("design -delete $abc9_map");
}
if (check_label("pre")) {
run("read_verilog -icells -lib -specify +/abc9_model.v");
- run("scc -specify -set_attr abc9_scc_id {}");
if (help_mode)
- run("abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)");
+ run("abc9_ops -break_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)");
else
- run("abc9_ops -mark_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : ""));
+ run("abc9_ops -break_scc -prep_delays -prep_xaiger" + std::string(dff_mode ? " -dff" : ""));
if (help_mode)
run("abc9_ops -prep_lut <maxlut>", "(skip if -lut or -luts)");
else if (!lut_mode)
@@ -445,6 +452,9 @@ struct Abc9Pass : public ScriptPass
run("design -delete $abc9_unmap");
if (saved_designs.count("$abc9_holes") || help_mode)
run("design -delete $abc9_holes");
+ if (help_mode || active_design->scratchpad_get_bool("abc9_ops.prep_bypass.did_something"))
+ run("delete =*_$abc9_byp");
+ run("setattr -mod -unset abc9_box_id");
}
}
} Abc9Pass;
diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc
index b916b049d..a66e95e21 100644
--- a/passes/techmap/abc9_exe.cc
+++ b/passes/techmap/abc9_exe.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc
index 98d0207c4..29fe74ec7 100644
--- a/passes/techmap/abc9_ops.cc
+++ b/passes/techmap/abc9_ops.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -155,21 +155,6 @@ void prep_hier(RTLIL::Design *design, bool dff_mode)
r.first->second = new Design;
Design *unmap_design = r.first->second;
- static const pool<IdString> seq_types{
- ID($dff), ID($dffsr), ID($adff),
- ID($dlatch), ID($dlatchsr), ID($sr),
- ID($mem),
- ID($_DFF_N_), ID($_DFF_P_),
- ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
- ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),
- ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
- ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
- ID($_DLATCH_N_), ID($_DLATCH_P_),
- ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_),
- ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_),
- ID($_SR_NN_), ID($_SR_NP_), ID($_SR_PN_), ID($_SR_PP_)
- };
-
for (auto module : design->selected_modules())
for (auto cell : module->cells()) {
auto inst_module = design->module(cell->type);
@@ -189,16 +174,22 @@ void prep_hier(RTLIL::Design *design, bool dff_mode)
derived_type = inst_module->derive(design, cell->parameters);
derived_module = design->module(derived_type);
}
- if (derived_module->get_blackbox_attribute(true /* ignore_wb */))
- continue;
if (derived_module->get_bool_attribute(ID::abc9_flop)) {
if (!dff_mode)
continue;
}
else {
- if (!derived_module->get_bool_attribute(ID::abc9_box) && !derived_module->get_bool_attribute(ID::abc9_bypass))
+ if (!derived_module->get_bool_attribute(ID::abc9_box) && !derived_module->get_bool_attribute(ID::abc9_bypass)) {
+ if (unmap_design->module(derived_type)) {
+ // If derived_type is present in unmap_design, it means that it was processed previously, but found to be incompatible -- e.g. if
+ // it contained a non-zero initial state. In this case, continue to replace the cell type/parameters so that it has the same properties
+ // as a compatible type, yet will be safely unmapped later
+ cell->type = derived_type;
+ cell->parameters.clear();
+ }
continue;
+ }
}
if (!unmap_design->module(derived_type)) {
@@ -223,7 +214,7 @@ void prep_hier(RTLIL::Design *design, bool dff_mode)
}
else if (derived_module->get_bool_attribute(ID::abc9_box)) {
for (auto derived_cell : derived_module->cells())
- if (seq_types.count(derived_cell->type)) {
+ if (derived_cell->is_mem_cell() || RTLIL::builtin_ff_cell_types().count(derived_cell->type)) {
derived_module->set_bool_attribute(ID::abc9_box, false);
derived_module->set_bool_attribute(ID::abc9_bypass);
break;
@@ -441,6 +432,8 @@ void prep_bypass(RTLIL::Design *design)
}
}
unmap_module->fixup_ports();
+
+ design->scratchpad_set_bool("abc9_ops.prep_bypass.did_something", true);
}
}
@@ -459,7 +452,14 @@ void prep_dff(RTLIL::Design *design)
if (!inst_module->get_bool_attribute(ID::abc9_flop))
continue;
log_assert(!inst_module->get_blackbox_attribute(true /* ignore_wb */));
- log_assert(cell->parameters.empty());
+ if (!cell->parameters.empty())
+ {
+ // At this stage of the ABC9 flow, cells instantiating (* abc9_flop *) modules must not contain any parameters -- instead it should
+ // be instantiating the derived module which will have had any parameters constant-propagated.
+ // This task is expected to be performed by `abc9_ops -prep_hier`, but it looks like it failed to do so for this design.
+ // Please file a bug report!
+ log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_flop *)\n", log_id(cell->name), log_id(cell->type));
+ }
modules_sel.select(inst_module);
}
}
@@ -544,18 +544,31 @@ void prep_dff_unmap(RTLIL::Design *design)
}
}
-void mark_scc(RTLIL::Module *module)
+void break_scc(RTLIL::Module *module)
{
// For every unique SCC found, (arbitrarily) find the first
- // cell in the component, and replace its output connections
- // with a new wire driven by the old connection but with a
- // special (* abc9_keep *) attribute set (which is used by
- // write_xaiger to break this wire into PI and POs)
+ // cell in the component, and interrupt all its output connections
+ // with the $__ABC9_SCC_BREAKER cell
+
+ // Do not break SCCs which have a cell instantiating an abc9_bypass-able
+ // module (but which wouldn't have been bypassed)
+ auto design = module->design;
+ pool<RTLIL::Cell*> scc_cells;
pool<RTLIL::Const> ids_seen;
for (auto cell : module->cells()) {
auto it = cell->attributes.find(ID::abc9_scc_id);
if (it == cell->attributes.end())
continue;
+ scc_cells.insert(cell);
+ auto inst_module = design->module(cell->type);
+ if (inst_module && inst_module->has_attribute(ID::abc9_bypass))
+ ids_seen.insert(it->second);
+ }
+
+ SigSpec I, O;
+ for (auto cell : scc_cells) {
+ auto it = cell->attributes.find(ID::abc9_scc_id);
+ log_assert(it != cell->attributes.end());
auto id = it->second;
auto r = ids_seen.insert(id);
cell->attributes.erase(it);
@@ -565,12 +578,21 @@ void mark_scc(RTLIL::Module *module)
if (c.second.is_fully_const()) continue;
if (cell->output(c.first)) {
Wire *w = module->addWire(NEW_ID, GetSize(c.second));
- w->set_bool_attribute(ID::abc9_keep);
- module->connect(w, c.second);
+ I.append(w);
+ O.append(c.second);
c.second = w;
}
}
}
+
+ if (!I.empty())
+ {
+ auto cell = module->addCell(NEW_ID, ID($__ABC9_SCC_BREAKER));
+ log_assert(GetSize(I) == GetSize(O));
+ cell->setParam(ID::WIDTH, GetSize(I));
+ cell->setPort(ID::I, std::move(I));
+ cell->setPort(ID::O, std::move(O));
+ }
}
void prep_delays(RTLIL::Design *design, bool dff_mode)
@@ -626,40 +648,38 @@ void prep_delays(RTLIL::Design *design, bool dff_mode)
auto inst_module = design->module(cell->type);
log_assert(inst_module);
- auto &t = timing.at(cell->type).required;
- for (auto &conn : cell->connections_) {
- auto port_wire = inst_module->wire(conn.first);
+ for (auto &i : timing.at(cell->type).required) {
+ auto port_wire = inst_module->wire(i.first.name);
if (!port_wire)
log_error("Port %s in cell %s (type %s) from module %s does not actually exist",
- log_id(conn.first), log_id(cell), log_id(cell->type), log_id(module));
- if (!port_wire->port_input)
- continue;
- if (conn.second.is_fully_const())
+ log_id(i.first.name), log_id(cell), log_id(cell->type), log_id(module));
+ log_assert(port_wire->port_input);
+
+ auto d = i.second.first;
+ if (d == 0)
continue;
- SigSpec O = module->addWire(NEW_ID, GetSize(conn.second));
- for (int i = 0; i < GetSize(conn.second); i++) {
- auto d = t.at(TimingInfo::NameBit(conn.first,i), 0);
- if (d == 0)
- continue;
+ auto offset = i.first.offset;
+ auto O = module->addWire(NEW_ID);
+ auto rhs = cell->getPort(i.first.name);
#ifndef NDEBUG
- if (ys_debug(1)) {
- static std::set<std::tuple<IdString,IdString,int>> seen;
- if (seen.emplace(cell->type, conn.first, i).second) log("%s.%s[%d] abc9_required = %d\n",
- log_id(cell->type), log_id(conn.first), i, d);
- }
+ if (ys_debug(1)) {
+ static pool<std::pair<IdString,TimingInfo::NameBit>> seen;
+ if (seen.emplace(cell->type, i.first).second) log("%s.%s[%d] abc9_required = %d\n",
+ log_id(cell->type), log_id(i.first.name), offset, d);
+ }
#endif
- auto r = box_cache.insert(d);
- if (r.second) {
- r.first->second = delay_module->derive(design, {{ID::DELAY, d}});
- log_assert(r.first->second.begins_with("$paramod$__ABC9_DELAY\\DELAY="));
- }
- auto box = module->addCell(NEW_ID, r.first->second);
- box->setPort(ID::I, conn.second[i]);
- box->setPort(ID::O, O[i]);
- conn.second[i] = O[i];
+ auto r = box_cache.insert(d);
+ if (r.second) {
+ r.first->second = delay_module->derive(design, {{ID::DELAY, d}});
+ log_assert(r.first->second.begins_with("$paramod$__ABC9_DELAY\\DELAY="));
}
+ auto box = module->addCell(NEW_ID, r.first->second);
+ box->setPort(ID::I, rhs[offset]);
+ box->setPort(ID::O, O);
+ rhs[offset] = O;
+ cell->setPort(i.first.name, rhs);
}
}
}
@@ -721,10 +741,8 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
bit_users[bit].insert(cell->name);
if (cell->output(conn.first) && !abc9_flop)
- for (const auto &chunk : conn.second.chunks())
- if (!chunk.wire->get_bool_attribute(ID::abc9_keep))
- for (auto b : sigmap(SigSpec(chunk)))
- bit_drivers[b].insert(cell->name);
+ for (auto bit : sigmap(conn.second))
+ bit_drivers[bit].insert(cell->name);
}
toposort.node(cell->name);
}
@@ -778,7 +796,14 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
continue;
if (!box_module->get_bool_attribute(ID::abc9_box))
continue;
- log_assert(cell->parameters.empty());
+ if (!cell->parameters.empty())
+ {
+ // At this stage of the ABC9 flow, cells instantiating (* abc9_box *) modules must not contain any parameters -- instead it should
+ // be instantiating the derived module which will have had any parameters constant-propagated.
+ // This task is expected to be performed by `abc9_ops -prep_hier`, but it looks like it failed to do so for this design.
+ // Please file a bug report!
+ log_error("Not expecting parameters on cell '%s' instantiating module '%s' marked (* abc9_box *)\n", log_id(cell_name), log_id(cell->type));
+ }
log_assert(box_module->get_blackbox_attribute());
cell->attributes[ID::abc9_box_seq] = box_count++;
@@ -787,7 +812,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff)
auto &holes_cell = r.first->second;
if (r.second) {
if (box_module->get_bool_attribute(ID::whitebox)) {
- holes_cell = holes_module->addCell(cell->name, cell->type);
+ holes_cell = holes_module->addCell(NEW_ID, cell->type);
if (box_module->has_processes())
Pass::call_on_module(design, box_module, "proc");
@@ -917,15 +942,8 @@ void prep_box(RTLIL::Design *design)
{
TimingInfo timing;
- std::stringstream ss;
int abc9_box_id = 1;
- for (auto module : design->modules()) {
- auto it = module->attributes.find(ID::abc9_box_id);
- if (it == module->attributes.end())
- continue;
- abc9_box_id = std::max(abc9_box_id, it->second.as_int());
- }
-
+ std::stringstream ss;
dict<IdString,std::vector<IdString>> box_ports;
for (auto module : design->modules()) {
auto it = module->attributes.find(ID::abc9_box);
@@ -986,16 +1004,16 @@ void prep_box(RTLIL::Design *design)
log_assert(GetSize(wire) == 1);
auto it = t.find(TimingInfo::NameBit(port_name,0));
if (it == t.end())
- // Assume no connectivity if no setup time
- ss << "-";
+ // Assume that no setup time means zero
+ ss << 0;
else {
- ss << it->second;
+ ss << it->second.first;
#ifndef NDEBUG
if (ys_debug(1)) {
static std::set<std::pair<IdString,IdString>> seen;
if (seen.emplace(module->name, port_name).second) log("%s.%s abc9_required = %d\n", log_id(module),
- log_id(port_name), it->second);
+ log_id(port_name), it->second.first);
}
#endif
}
@@ -1416,7 +1434,6 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
RTLIL::Wire *mapped_wire = mapped_mod->wire(port);
RTLIL::Wire *wire = module->wire(port);
log_assert(wire);
- wire->attributes.erase(ID::abc9_keep);
RTLIL::Wire *remap_wire = module->wire(remap_name(port));
RTLIL::SigSpec signal(wire, remap_wire->start_offset-wire->start_offset, GetSize(remap_wire));
@@ -1579,11 +1596,11 @@ struct Abc9OpsPass : public Pass {
log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n");
log(" certain required times.\n");
log("\n");
- log(" -mark_scc\n");
+ log(" -break_scc\n");
log(" for an arbitrarily chosen cell in each unique SCC of each selected module\n");
- log(" (tagged with an (* abc9_scc_id = <int> *) attribute), temporarily mark all\n");
- log(" wires driven by this cell's outputs with a (* keep *) attribute in order\n");
- log(" to break the SCC. this temporary attribute will be removed on -reintegrate.\n");
+ log(" (tagged with an (* abc9_scc_id = <int> *) attribute) interrupt all wires\n");
+ log(" driven by this cell's outputs with a temporary $__ABC9_SCC_BREAKER cell\n");
+ log(" to break the SCC.\n");
log("\n");
log(" -prep_xaiger\n");
log(" prepare the design for XAIGER output. this includes computing the\n");
@@ -1620,7 +1637,7 @@ struct Abc9OpsPass : public Pass {
bool check_mode = false;
bool prep_delays_mode = false;
- bool mark_scc_mode = false;
+ bool break_scc_mode = false;
bool prep_hier_mode = false;
bool prep_bypass_mode = false;
bool prep_dff_mode = false, prep_dff_submod_mode = false, prep_dff_unmap_mode = false;
@@ -1642,8 +1659,8 @@ struct Abc9OpsPass : public Pass {
valid = true;
continue;
}
- if (arg == "-mark_scc") {
- mark_scc_mode = true;
+ if (arg == "-break_scc") {
+ break_scc_mode = true;
valid = true;
continue;
}
@@ -1719,7 +1736,7 @@ struct Abc9OpsPass : public Pass {
extra_args(args, argidx, design);
if (!valid)
- log_cmd_error("At least one of -check, -mark_scc, -prep_{delays,xaiger,dff[123],lut,box}, -write_{lut,box}, -reintegrate must be specified.\n");
+ log_cmd_error("At least one of -check, -break_scc, -prep_{delays,xaiger,dff[123],lut,box}, -write_{lut,box}, -reintegrate must be specified.\n");
if (dff_mode && !check_mode && !prep_hier_mode && !prep_delays_mode && !prep_xaiger_mode && !reintegrate_mode)
log_cmd_error("'-dff' option is only relevant for -prep_{hier,delay,xaiger} or -reintegrate.\n");
@@ -1756,8 +1773,8 @@ struct Abc9OpsPass : public Pass {
write_lut(mod, write_lut_dst);
if (!write_box_dst.empty())
write_box(mod, write_box_dst);
- if (mark_scc_mode)
- mark_scc(mod);
+ if (break_scc_mode)
+ break_scc(mod);
if (prep_xaiger_mode)
prep_xaiger(mod, dff_mode);
if (reintegrate_mode)
diff --git a/passes/techmap/aigmap.cc b/passes/techmap/aigmap.cc
index ce151c7f3..4836ebe34 100644
--- a/passes/techmap/aigmap.cc
+++ b/passes/techmap/aigmap.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc
index b16e9750e..e4e70004c 100644
--- a/passes/techmap/alumacc.cc
+++ b/passes/techmap/alumacc.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/attrmap.cc b/passes/techmap/attrmap.cc
index 8643543c8..96e65ff2e 100644
--- a/passes/techmap/attrmap.cc
+++ b/passes/techmap/attrmap.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/attrmvcp.cc b/passes/techmap/attrmvcp.cc
index b3202c587..65b63daf1 100644
--- a/passes/techmap/attrmvcp.cc
+++ b/passes/techmap/attrmvcp.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/bmuxmap.cc b/passes/techmap/bmuxmap.cc
new file mode 100644
index 000000000..03673c278
--- /dev/null
+++ b/passes/techmap/bmuxmap.cc
@@ -0,0 +1,76 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2022 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * 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
+
+struct BmuxmapPass : public Pass {
+ BmuxmapPass() : Pass("bmuxmap", "transform $bmux cells to trees of $mux cells") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" bmuxmap [selection]\n");
+ log("\n");
+ log("This pass transforms $bmux cells to trees of $mux cells.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing BMUXMAP pass.\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type != ID($bmux))
+ continue;
+
+ SigSpec sel = cell->getPort(ID::S);
+ SigSpec data = cell->getPort(ID::A);
+ int width = GetSize(cell->getPort(ID::Y));
+
+ for (int idx = 0; idx < GetSize(sel); idx++) {
+ SigSpec new_data = module->addWire(NEW_ID, GetSize(data)/2);
+ for (int i = 0; i < GetSize(new_data); i += width) {
+ RTLIL::Cell *mux = module->addMux(NEW_ID,
+ data.extract(i*2, width),
+ data.extract(i*2+width, width),
+ sel[idx],
+ new_data.extract(i, width));
+ mux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ }
+ data = new_data;
+ }
+
+ module->connect(cell->getPort(ID::Y), data);
+ module->remove(cell);
+ }
+ }
+} BmuxmapPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/clkbufmap.cc b/passes/techmap/clkbufmap.cc
index 1cbd12e3d..a7b96a9c6 100644
--- a/passes/techmap/clkbufmap.cc
+++ b/passes/techmap/clkbufmap.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2019 Marcelina Kościelnicka <mwk@0x04.net>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/techmap/deminout.cc b/passes/techmap/deminout.cc
index 9a23cb90e..5245331f8 100644
--- a/passes/techmap/deminout.cc
+++ b/passes/techmap/deminout.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/demuxmap.cc b/passes/techmap/demuxmap.cc
new file mode 100644
index 000000000..292b18bad
--- /dev/null
+++ b/passes/techmap/demuxmap.cc
@@ -0,0 +1,80 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2022 Marcelina Kościelnicka <mwk@0x04.net>
+ *
+ * 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
+
+struct DemuxmapPass : public Pass {
+ DemuxmapPass() : Pass("demuxmap", "transform $demux cells to $eq + $mux cells") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" demuxmap [selection]\n");
+ log("\n");
+ log("This pass transforms $demux cells to a bunch of equality comparisons.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing DEMUXMAP pass.\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type != ID($demux))
+ continue;
+
+ SigSpec sel = cell->getPort(ID::S);
+ SigSpec data = cell->getPort(ID::A);
+ SigSpec out = cell->getPort(ID::Y);
+ int width = GetSize(cell->getPort(ID::A));
+
+ for (int i = 0; i < 1 << GetSize(sel); i++) {
+ if (width == 1 && data == State::S1) {
+ RTLIL::Cell *eq_cell = module->addEq(NEW_ID, sel, Const(i, GetSize(sel)), out[i]);
+ eq_cell->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ } else {
+ Wire *eq = module->addWire(NEW_ID);
+ RTLIL::Cell *eq_cell = module->addEq(NEW_ID, sel, Const(i, GetSize(sel)), eq);
+ eq_cell->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ RTLIL::Cell *mux = module->addMux(NEW_ID,
+ Const(State::S0, width),
+ data,
+ eq,
+ out.extract(i*width, width));
+ mux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ }
+ }
+
+ module->remove(cell);
+ }
+ }
+} DemuxmapPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc
index 44af043db..9cfe55947 100644
--- a/passes/techmap/dffinit.cc
+++ b/passes/techmap/dffinit.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/dfflegalize.cc b/passes/techmap/dfflegalize.cc
index c1e7e557d..1d99caa3a 100644
--- a/passes/techmap/dfflegalize.cc
+++ b/passes/techmap/dfflegalize.cc
@@ -20,6 +20,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include "kernel/ffinit.h"
+#include "kernel/ff.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -27,38 +28,42 @@ PRIVATE_NAMESPACE_BEGIN
enum FfType {
FF_DFF,
FF_DFFE,
- FF_ADFF0,
- FF_ADFF1,
- FF_ADFFE0,
- FF_ADFFE1,
+ FF_ADFF,
+ FF_ADFFE,
+ FF_ALDFF,
+ FF_ALDFFE,
FF_DFFSR,
FF_DFFSRE,
- FF_SDFF0,
- FF_SDFF1,
- FF_SDFFE0,
- FF_SDFFE1,
- FF_SDFFCE0,
- FF_SDFFCE1,
+ FF_SDFF,
+ FF_SDFFE,
+ FF_SDFFCE,
+ FF_RLATCH,
FF_SR,
FF_DLATCH,
- FF_ADLATCH0,
- FF_ADLATCH1,
+ FF_ADLATCH,
FF_DLATCHSR,
NUM_FFTYPES,
};
enum FfNeg {
- NEG_R = 0x1,
- NEG_S = 0x2,
- NEG_E = 0x4,
- NEG_C = 0x8,
- NUM_NEG = 0x10,
+ NEG_CE = 0x1,
+ NEG_R = 0x2,
+ NEG_S = 0x4,
+ NEG_L = 0x8,
+ NEG_C = 0x10,
+ NUM_NEG = 0x20,
};
enum FfInit {
INIT_X = 0x1,
INIT_0 = 0x2,
INIT_1 = 0x4,
+ INIT_X_R0 = 0x10,
+ INIT_0_R0 = 0x20,
+ INIT_1_R0 = 0x40,
+ INIT_X_R1 = 0x100,
+ INIT_0_R1 = 0x200,
+ INIT_1_R1 = 0x400,
};
struct DffLegalizePass : public Pass {
@@ -101,6 +106,8 @@ struct DffLegalizePass : public Pass {
log("- $_DFFE_[NP][NP]_\n");
log("- $_DFF_[NP][NP][01]_\n");
log("- $_DFFE_[NP][NP][01][NP]_\n");
+ log("- $_ALDFF_[NP][NP]_\n");
+ log("- $_ALDFFE_[NP][NP][NP]_\n");
log("- $_DFFSR_[NP][NP][NP]_\n");
log("- $_DFFSRE_[NP][NP][NP][NP]_\n");
log("- $_SDFF_[NP][NP][01]_\n");
@@ -151,18 +158,30 @@ struct DffLegalizePass : public Pass {
int supported_cells[NUM_FFTYPES];
// Aggregated for all *dff* cells.
int supported_dff;
+ // Aggregated for all *dffe* cells.
+ int supported_dffe;
// Aggregated for all dffsr* cells.
int supported_dffsr;
- // Aggregated for all adff* cells.
- int supported_adff0;
- int supported_adff1;
+ // Aggregated for all aldff cells.
+ int supported_aldff;
+ // Aggregated for all aldffe cells.
+ int supported_aldffe;
+ // Aggregated for all adff* cells and trivial emulations.
+ int supported_adff;
+ // Aggregated for all adffe* cells and trivial emulations.
+ int supported_adffe;
// Aggregated for all sdff* cells.
- int supported_sdff0;
- int supported_sdff1;
+ int supported_sdff;
// Aggregated for all ways to obtain a SR latch.
int supported_sr;
+ int supported_sr_plain;
// Aggregated for all *dlatch* cells.
int supported_dlatch;
+ int supported_dlatch_plain;
+ // Aggregated for all ways to obtain an R latch.
+ int supported_rlatch;
+ // Aggregated for all adlatch cells and trivial emulations.
+ int supported_adlatch;
int mince;
int minsrst;
@@ -179,736 +198,794 @@ struct DffLegalizePass : public Pass {
res |= INIT_1;
if (mask & INIT_1)
res |= INIT_0;
+ if (mask & INIT_X_R0)
+ res |= INIT_X_R1;
+ if (mask & INIT_0_R0)
+ res |= INIT_1_R1;
+ if (mask & INIT_1_R0)
+ res |= INIT_0_R1;
+ if (mask & INIT_X_R1)
+ res |= INIT_X_R0;
+ if (mask & INIT_0_R1)
+ res |= INIT_1_R0;
+ if (mask & INIT_1_R1)
+ res |= INIT_0_R0;
return res;
}
- void handle_ff(Cell *cell) {
- std::string type_str = cell->type.str();
-
- FfType ff_type;
- int ff_neg = 0;
- SigSpec sig_d;
- SigSpec sig_q;
- SigSpec sig_c;
- SigSpec sig_e;
- SigSpec sig_r;
- SigSpec sig_s;
- bool has_srst = false;
-
- if (cell->hasPort(ID::D))
- sig_d = cell->getPort(ID::D);
- if (cell->hasPort(ID::Q))
- sig_q = cell->getPort(ID::Q);
- if (cell->hasPort(ID::C))
- sig_c = cell->getPort(ID::C);
- if (cell->hasPort(ID::E))
- sig_e = cell->getPort(ID::E);
- if (cell->hasPort(ID::R))
- sig_r = cell->getPort(ID::R);
- if (cell->hasPort(ID::S))
- sig_s = cell->getPort(ID::S);
-
- if (type_str.substr(0, 5) == "$_SR_") {
- ff_type = FF_SR;
- if (type_str[5] == 'N')
- ff_neg |= NEG_S;
- if (type_str[6] == 'N')
- ff_neg |= NEG_R;
- } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 8) {
- ff_type = FF_DFF;
- if (type_str[6] == 'N')
- ff_neg |= NEG_C;
- } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 10) {
- ff_type = FF_DFFE;
- if (type_str[7] == 'N')
- ff_neg |= NEG_C;
- if (type_str[8] == 'N')
- ff_neg |= NEG_E;
- } else if (type_str.substr(0, 6) == "$_DFF_" && type_str.size() == 10) {
- ff_type = type_str[8] == '1' ? FF_ADFF1 : FF_ADFF0;
- if (type_str[6] == 'N')
- ff_neg |= NEG_C;
- if (type_str[7] == 'N')
- ff_neg |= NEG_R;
- } else if (type_str.substr(0, 7) == "$_DFFE_" && type_str.size() == 12) {
- ff_type = type_str[9] == '1' ? FF_ADFFE1 : FF_ADFFE0;
- if (type_str[7] == 'N')
- ff_neg |= NEG_C;
- if (type_str[8] == 'N')
- ff_neg |= NEG_R;
- if (type_str[10] == 'N')
- ff_neg |= NEG_E;
- } else if (type_str.substr(0, 8) == "$_DFFSR_" && type_str.size() == 12) {
- ff_type = FF_DFFSR;
- if (type_str[8] == 'N')
- ff_neg |= NEG_C;
- if (type_str[9] == 'N')
- ff_neg |= NEG_S;
- if (type_str[10] == 'N')
- ff_neg |= NEG_R;
- } else if (type_str.substr(0, 9) == "$_DFFSRE_" && type_str.size() == 14) {
- ff_type = FF_DFFSRE;
- if (type_str[9] == 'N')
- ff_neg |= NEG_C;
- if (type_str[10] == 'N')
- ff_neg |= NEG_S;
- if (type_str[11] == 'N')
- ff_neg |= NEG_R;
- if (type_str[12] == 'N')
- ff_neg |= NEG_E;
- } else if (type_str.substr(0, 7) == "$_SDFF_" && type_str.size() == 11) {
- ff_type = type_str[9] == '1' ? FF_SDFF1 : FF_SDFF0;
- if (type_str[7] == 'N')
- ff_neg |= NEG_C;
- if (type_str[8] == 'N')
- ff_neg |= NEG_R;
- has_srst = true;
- } else if (type_str.substr(0, 8) == "$_SDFFE_" && type_str.size() == 13) {
- ff_type = type_str[10] == '1' ? FF_SDFFE1 : FF_SDFFE0;
- if (type_str[8] == 'N')
- ff_neg |= NEG_C;
- if (type_str[9] == 'N')
- ff_neg |= NEG_R;
- if (type_str[11] == 'N')
- ff_neg |= NEG_E;
- has_srst = true;
- } else if (type_str.substr(0, 9) == "$_SDFFCE_" && type_str.size() == 14) {
- ff_type = type_str[11] == '1' ? FF_SDFFCE1 : FF_SDFFCE0;
- if (type_str[9] == 'N')
- ff_neg |= NEG_C;
- if (type_str[10] == 'N')
- ff_neg |= NEG_R;
- if (type_str[12] == 'N')
- ff_neg |= NEG_E;
- has_srst = true;
- } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 11) {
- ff_type = FF_DLATCH;
- if (type_str[9] == 'N')
- ff_neg |= NEG_E;
- } else if (type_str.substr(0, 9) == "$_DLATCH_" && type_str.size() == 13) {
- ff_type = type_str[11] == '1' ? FF_ADLATCH1 : FF_ADLATCH0;
- if (type_str[9] == 'N')
- ff_neg |= NEG_E;
- if (type_str[10] == 'N')
- ff_neg |= NEG_R;
- } else if (type_str.substr(0, 11) == "$_DLATCHSR_" && type_str.size() == 15) {
- ff_type = FF_DLATCHSR;
- if (type_str[11] == 'N')
- ff_neg |= NEG_E;
- if (type_str[12] == 'N')
- ff_neg |= NEG_S;
- if (type_str[13] == 'N')
- ff_neg |= NEG_R;
+ int get_ff_type(const FfData &ff) {
+ if (ff.has_clk) {
+ if (ff.has_sr) {
+ return ff.has_ce ? FF_DFFSRE : FF_DFFSR;
+ } else if (ff.has_arst) {
+ return ff.has_ce ? FF_ADFFE : FF_ADFF;
+ } else if (ff.has_aload) {
+ return ff.has_ce ? FF_ALDFFE : FF_ALDFF;
+ } else if (ff.has_srst) {
+ if (ff.has_ce)
+ return ff.ce_over_srst ? FF_SDFFCE : FF_SDFFE;
+ else
+ return FF_SDFF;
+ } else {
+ return ff.has_ce ? FF_DFFE : FF_DFF;
+ }
} else {
- log_warning("Ignoring unknown ff type %s [%s.%s].\n", log_id(cell->type), log_id(cell->module->name), log_id(cell->name));
- return;
+ if (ff.has_aload) {
+ if (ff.has_sr)
+ return FF_DLATCHSR;
+ else if (ff.has_arst)
+ return FF_ADLATCH;
+ else
+ return FF_DLATCH;
+ } else {
+ if (ff.has_sr) {
+ return FF_SR;
+ } else if (ff.has_arst) {
+ return FF_RLATCH;
+ } else {
+ log_assert(0);
+ return 0;
+ }
+ }
+ }
+ }
+
+ int get_initmask(FfData &ff) {
+ int res = 0;
+ if (ff.val_init[0] == State::S0)
+ res = INIT_0;
+ else if (ff.val_init[0] == State::S1)
+ res = INIT_1;
+ else
+ res = INIT_X;
+ if (ff.has_arst) {
+ if (ff.val_arst[0] == State::S0)
+ res <<= 4;
+ else if (ff.val_arst[0] == State::S1)
+ res <<= 8;
+ } else if (ff.has_srst) {
+ if (ff.val_srst[0] == State::S0)
+ res <<= 4;
+ else if (ff.val_srst[0] == State::S1)
+ res <<= 8;
+ }
+ return res;
+ }
+
+ void fail_ff(const FfData &ff, const char *reason) {
+ log_error("FF %s.%s (type %s) cannot be legalized: %s\n", log_id(ff.module->name), log_id(ff.cell->name), log_id(ff.cell->type), reason);
+ }
+
+ bool try_flip(FfData &ff, int supported_mask) {
+ int initmask = get_initmask(ff);
+ if (supported_mask & initmask)
+ return true;
+ if (supported_mask & flip_initmask(initmask)) {
+ ff.flip_bits({0});
+ return true;
}
+ return false;
+ }
- State initval = initvals(sig_q[0]);
-
- FfInit initmask = INIT_X;
- if (initval == State::S0)
- initmask = INIT_0;
- else if (initval == State::S1)
- initmask = INIT_1;
- const char *reason;
+ void emulate_split_init_arst(FfData &ff) {
+ ff.remove();
- bool kill_ce = mince && GetSize(sig_c) && GetSize(sig_e) && sig_e[0].wire && ce_used[sig_e[0]] < mince;
- bool kill_srst = minsrst && has_srst && sig_r[0].wire && srst_used[sig_r[0]] < minsrst;
+ FfData ff_dff(ff.module, &initvals, NEW_ID);
+ ff_dff.width = ff.width;
+ ff_dff.has_aload = ff.has_aload;
+ ff_dff.sig_aload = ff.sig_aload;
+ ff_dff.pol_aload = ff.pol_aload;
+ ff_dff.sig_ad = ff.sig_ad;
+ ff_dff.has_clk = ff.has_clk;
+ ff_dff.sig_clk = ff.sig_clk;
+ ff_dff.pol_clk = ff.pol_clk;
+ ff_dff.sig_d = ff.sig_d;
+ ff_dff.has_ce = ff.has_ce;
+ ff_dff.sig_ce = ff.sig_ce;
+ ff_dff.pol_ce = ff.pol_ce;
+ ff_dff.sig_q = ff.module->addWire(NEW_ID, ff.width);
+ ff_dff.val_init = ff.val_init;
+ ff_dff.is_fine = ff.is_fine;
- while (!(supported_cells[ff_type] & initmask) || kill_ce || kill_srst) {
- // Well, cell is not directly supported. Decide how to deal with it.
+ FfData ff_adff(ff.module, &initvals, NEW_ID);
+ ff_adff.width = ff.width;
+ ff_adff.has_aload = ff.has_aload;
+ ff_adff.sig_aload = ff.sig_aload;
+ ff_adff.pol_aload = ff.pol_aload;
+ ff_adff.sig_ad = ff.sig_ad;
+ ff_adff.has_clk = ff.has_clk;
+ ff_adff.sig_clk = ff.sig_clk;
+ ff_adff.pol_clk = ff.pol_clk;
+ ff_adff.sig_d = ff.sig_d;
+ ff_adff.has_ce = ff.has_ce;
+ ff_adff.sig_ce = ff.sig_ce;
+ ff_adff.pol_ce = ff.pol_ce;
+ ff_adff.sig_q = ff.module->addWire(NEW_ID, ff.width);
+ ff_adff.val_init = Const(State::Sx, ff.width);
+ ff_adff.has_arst = true;
+ ff_adff.sig_arst = ff.sig_arst;
+ ff_adff.pol_arst = ff.pol_arst;
+ ff_adff.val_arst = ff.val_arst;
+ ff_adff.is_fine = ff.is_fine;
- if (ff_type == FF_DFF || ff_type == FF_DFFE) {
- if (kill_ce) {
- ff_type = FF_DFF;
- goto unmap_enable;
- }
- if (!(supported_dff & initmask)) {
- // This init value is not supported at all...
- if (supported_dff & flip_initmask(initmask)) {
- // The other one is, though. Negate D, Q, and init.
-flip_dqi:
- if (initval == State::S0) {
- initval = State::S1;
- initmask = INIT_1;
- } else if (initval == State::S1) {
- initval = State::S0;
- initmask = INIT_0;
- }
- if (ff_type != FF_SR)
- sig_d = cell->module->NotGate(NEW_ID, sig_d[0]);
- SigBit new_q = SigSpec(cell->module->addWire(NEW_ID))[0];
- cell->module->addNotGate(NEW_ID, new_q, sig_q[0]);
- initvals.remove_init(sig_q[0]);
- initvals.set_init(new_q, initval);
- sig_q = new_q;
- continue;
- }
- if (!supported_dff)
- reason = "dffs are not supported";
- else
- reason = "initialized dffs are not supported";
- goto error;
- }
+ FfData ff_sel(ff.module, &initvals, NEW_ID);
+ ff_sel.width = 1;
+ ff_sel.sig_q = ff.module->addWire(NEW_ID);
+ ff_sel.has_arst = true;
+ ff_sel.sig_arst = ff.sig_arst;
+ ff_sel.pol_arst = ff.pol_arst;
+ ff_sel.val_arst = State::S1;
+ ff_sel.val_init = State::S0;
+ ff_sel.is_fine = ff.is_fine;
- // Some DFF is supported with this init val. Just pick a type.
- if (ff_type == FF_DFF) {
- // Try adding a set or reset pin.
- for (auto new_type: {FF_SDFF0, FF_SDFF1, FF_ADFF0, FF_ADFF1})
- if (supported_cells[new_type] & initmask) {
- ff_type = new_type;
- sig_r = State::S0;
- goto cell_ok;
- }
- // Try adding both.
- if (supported_cells[FF_DFFSR] & initmask) {
- ff_type = FF_DFFSR;
- sig_r = State::S0;
- sig_s = State::S0;
- break;
- }
- // Nope. Will need to add enable and go the DFFE route.
- sig_e = State::S1;
- if (supported_cells[FF_DFFE] & initmask) {
- ff_type = FF_DFFE;
- break;
- }
- }
- // Try adding a set or reset pin.
- for (auto new_type: {FF_SDFFE0, FF_SDFFE1, FF_SDFFCE0, FF_SDFFCE1, FF_ADFFE0, FF_ADFFE1})
- if (supported_cells[new_type] & initmask) {
- ff_type = new_type;
- sig_r = State::S0;
- goto cell_ok;
- }
- // Try adding both.
- if (supported_cells[FF_DFFSRE] & initmask) {
- ff_type = FF_DFFSRE;
- sig_r = State::S0;
- sig_s = State::S0;
- break;
- }
+ if (ff.is_fine)
+ ff.module->addMuxGate(NEW_ID, ff_dff.sig_q, ff_adff.sig_q, ff_sel.sig_q, ff.sig_q);
+ else
+ ff.module->addMux(NEW_ID, ff_dff.sig_q, ff_adff.sig_q, ff_sel.sig_q, ff.sig_q);
+
+ legalize_ff(ff_dff);
+ legalize_ff(ff_adff);
+ legalize_ff(ff_sel);
+ }
- // Seems that no DFFs with enable are supported.
- // The enable input needs to be unmapped.
- // This should not be reached if we started from plain DFF.
- log_assert(ff_type == FF_DFFE);
- ff_type = FF_DFF;
-unmap_enable:
- if (ff_neg & NEG_E)
- sig_d = cell->module->MuxGate(NEW_ID, sig_d[0], sig_q[0], sig_e[0]);
+ void emulate_split_set_clr(FfData &ff) {
+ // No native DFFSR. However, if we can conjure
+ // a SR latch and ADFF, it can still be emulated.
+ int initmask = get_initmask(ff);
+ int flipmask = flip_initmask(initmask);
+ bool init_clr = true;
+ bool init_set = true;
+ State initsel = State::Sx;
+ int supported_arst = ff.has_clk ? supported_adff : supported_adlatch;
+ bool init_clr_ok = (supported_arst & initmask << 4) || (supported_arst & flipmask << 8);
+ bool init_set_ok = (supported_arst & initmask << 8) || (supported_arst & flipmask << 4);
+ if (init_clr_ok && init_set_ok && supported_sr) {
+ // OK
+ } else if (init_clr_ok && (supported_sr & INIT_0)) {
+ init_set = false;
+ initsel = State::S0;
+ } else if (init_set_ok && (supported_sr & INIT_1)) {
+ init_clr = false;
+ initsel = State::S1;
+ } else if (init_clr_ok && (supported_sr & INIT_1)) {
+ init_set = false;
+ initsel = State::S0;
+ } else if (init_set_ok && (supported_sr & INIT_0)) {
+ init_clr = false;
+ initsel = State::S1;
+ } else {
+ if (ff.has_clk) {
+ if (!supported_dffsr)
+ fail_ff(ff, "dffs with async set and reset are not supported");
else
- sig_d = cell->module->MuxGate(NEW_ID, sig_q[0], sig_d[0], sig_e[0]);
- ff_neg &= ~NEG_E;
- sig_e = SigSpec();
- kill_ce = false;
- // Now try again as plain DFF.
- continue;
- } else if (ff_type == FF_ADFF0 || ff_type == FF_ADFF1 || ff_type == FF_ADFFE0 || ff_type == FF_ADFFE1) {
- bool has_set = ff_type == FF_ADFF1 || ff_type == FF_ADFFE1;
- bool has_en = ff_type == FF_ADFFE0 || ff_type == FF_ADFFE1;
- if (kill_ce) {
- ff_type = has_set ? FF_ADFF1 : FF_ADFF0;
- goto unmap_enable;
- }
- if (!has_en && (supported_cells[has_set ? FF_ADFFE1 : FF_ADFFE0] & initmask)) {
- // Just add enable.
- sig_e = State::S1;
- ff_type = has_set ? FF_ADFFE1 : FF_ADFFE0;
- break;
- }
- if (supported_cells[has_en ? FF_DFFSRE : FF_DFFSR] & initmask) {
-adff_to_dffsr:
- // Throw in a set/reset, retry in DFFSR/DFFSRE branch.
- if (has_set) {
- sig_s = sig_r;
- sig_r = State::S0;
- if (ff_neg & NEG_R) {
- ff_neg &= ~NEG_R;
- ff_neg |= NEG_S;
- }
- } else {
- sig_s = State::S0;
- }
- if (has_en)
- ff_type = FF_DFFSRE;
- else
- ff_type = FF_DFFSR;
- continue;
- }
- if (has_en && (supported_cells[has_set ? FF_ADFF1 : FF_ADFF0] & initmask)) {
- // Unmap enable.
- ff_type = has_set ? FF_ADFF1 : FF_ADFF0;
- goto unmap_enable;
- }
- if (supported_dffsr & initmask) {
- goto adff_to_dffsr;
- }
- log_assert(!((has_set ? supported_adff1 : supported_adff0) & initmask));
- // Alright, so this particular combination of initval and
- // resetval is not natively supported. First, try flipping
- // them both to see whether this helps.
- int flipmask = flip_initmask(initmask);
- if ((has_set ? supported_adff0 : supported_adff1) & flipmask) {
- // Checks out, do it.
- ff_type = has_en ? (has_set ? FF_ADFFE0 : FF_ADFFE1) : (has_set ? FF_ADFF0 : FF_ADFF1);
- goto flip_dqi;
- }
+ fail_ff(ff, "initialized dffs with async set and reset are not supported");
+ } else {
+ if (!supported_cells[FF_DLATCHSR])
+ fail_ff(ff, "dlatch with async set and reset are not supported");
+ else
+ fail_ff(ff, "initialized dlatch with async set and reset are not supported");
+ }
+ }
- if (!supported_adff0 && !supported_adff1) {
- reason = "dffs with async set or reset are not supported";
- goto error;
- }
- if (!(supported_dff & ~INIT_X)) {
- reason = "initialized dffs are not supported";
- goto error;
- }
- // If we got here, initialized dff is supported, but not this
- // particular reset+init combination (nor its negation).
- // The only hope left is breaking down to adff + dff + dlatch + mux.
- if (!(supported_dlatch & ~INIT_X)) {
- reason = "unsupported initial value and async reset value combination";
- goto error;
- }
+ // If we have to unmap enable anyway, do it before breakdown.
+ if (ff.has_ce && !supported_cells[FF_ADFFE])
+ ff.unmap_ce();
- // If we have to unmap enable anyway, do it before breakdown.
- if (has_en && !supported_cells[FF_ADFFE0] && !supported_cells[FF_ADFFE1]) {
- ff_type = has_set ? FF_ADFF1 : FF_ADFF0;
- goto unmap_enable;
- }
+ log_warning("Emulating async set + reset with several FFs and a mux for %s.%s\n", log_id(ff.module->name), log_id(ff.cell->name));
- log_warning("Emulating mismatched async reset and init with several FFs and a mux for %s.%s\n", log_id(cell->module->name), log_id(cell->name));
- initvals.remove_init(sig_q[0]);
- Wire *adff_q = cell->module->addWire(NEW_ID);
- Wire *dff_q = cell->module->addWire(NEW_ID);
- Wire *sel_q = cell->module->addWire(NEW_ID);
- initvals.set_init(SigBit(dff_q, 0), initval);
- initvals.set_init(SigBit(sel_q, 0), State::S0);
- Cell *cell_dff;
- Cell *cell_adff;
- Cell *cell_sel;
- if (!has_en) {
- cell_dff = cell->module->addDffGate(NEW_ID, sig_c, sig_d, dff_q, !(ff_neg & NEG_C));
- cell_adff = cell->module->addAdffGate(NEW_ID, sig_c, sig_r, sig_d, adff_q, has_set, !(ff_neg & NEG_C), !(ff_neg & NEG_R));
- } else {
- cell_dff = cell->module->addDffeGate(NEW_ID, sig_c, sig_e, sig_d, dff_q, !(ff_neg & NEG_C), !(ff_neg & NEG_E));
- cell_adff = cell->module->addAdffeGate(NEW_ID, sig_c, sig_e, sig_r, sig_d, adff_q, has_set, !(ff_neg & NEG_C), !(ff_neg & NEG_E), !(ff_neg & NEG_R));
- }
- cell_sel = cell->module->addDlatchGate(NEW_ID, sig_r, State::S1, sel_q, !(ff_neg & NEG_R));
- cell->module->addMuxGate(NEW_ID, dff_q, adff_q, sel_q, sig_q);
-
- // Bye, cell.
- cell->module->remove(cell);
- handle_ff(cell_dff);
- handle_ff(cell_adff);
- handle_ff(cell_sel);
- return;
- } else if (ff_type == FF_DFFSR || ff_type == FF_DFFSRE) {
- if (kill_ce) {
- ff_type = FF_DFFSR;
- goto unmap_enable;
- }
- // First, see if mapping/unmapping enable will help.
- if (supported_cells[FF_DFFSRE] & initmask) {
- ff_type = FF_DFFSRE;
- sig_e = State::S1;
- break;
- }
- if (supported_cells[FF_DFFSR] & initmask) {
- ff_type = FF_DFFSR;
- goto unmap_enable;
- }
- if (supported_dffsr & flip_initmask(initmask)) {
-flip_dqisr:;
- log_warning("Flipping D/Q/init and inserting set/reset fixup to handle init value on %s.%s [%s]\n", log_id(cell->module->name), log_id(cell->name), log_id(cell->type));
- SigSpec new_r;
- bool neg_r = (ff_neg & NEG_R);
- bool neg_s = (ff_neg & NEG_S);
- if (!(ff_neg & NEG_S)) {
- if (!(ff_neg & NEG_R))
- new_r = cell->module->AndnotGate(NEW_ID, sig_s, sig_r);
- else
- new_r = cell->module->AndGate(NEW_ID, sig_s, sig_r);
- } else {
- if (!(ff_neg & NEG_R))
- new_r = cell->module->OrGate(NEW_ID, sig_s, sig_r);
- else
- new_r = cell->module->OrnotGate(NEW_ID, sig_s, sig_r);
- }
- ff_neg &= ~(NEG_R | NEG_S);
- if (neg_r)
- ff_neg |= NEG_S;
- if (neg_s)
- ff_neg |= NEG_R;
- sig_s = sig_r;
- sig_r = new_r;
- goto flip_dqi;
- }
- // No native DFFSR. However, if we can conjure
- // a SR latch and ADFF, it can still be emulated.
- int flipmask = flip_initmask(initmask);
- bool init0 = true;
- bool init1 = true;
- State initsel = State::Sx;
- if (((supported_adff0 & initmask) || (supported_adff1 & flipmask)) && ((supported_adff1 & initmask) || (supported_adff0 & flipmask)) && supported_sr) {
- // OK
- } else if (((supported_adff0 & initmask) || (supported_adff1 & flipmask)) && (supported_sr & INIT_0)) {
- init1 = false;
- initsel = State::S0;
- } else if (((supported_adff1 & initmask) || (supported_adff0 & flipmask)) && (supported_sr & INIT_1)) {
- init0 = false;
- initsel = State::S1;
- } else if (((supported_adff0 & initmask) || (supported_adff1 & flipmask)) && (supported_sr & INIT_1)) {
- init1 = false;
- initsel = State::S0;
- } else if (((supported_adff1 & initmask) || (supported_adff0 & flipmask)) && (supported_sr & INIT_0)) {
- init0 = false;
- initsel = State::S1;
- } else {
- if (!supported_dffsr)
- reason = "dffs with async set and reset are not supported";
- else
- reason = "initialized dffs with async set and reset are not supported";
- goto error;
- }
+ log_assert(ff.width == 1);
+ ff.remove();
- // If we have to unmap enable anyway, do it before breakdown.
- if (ff_type == FF_DFFSRE && !supported_cells[FF_ADFFE0] && !supported_cells[FF_ADFFE1]) {
- ff_type = FF_DFFSR;
- goto unmap_enable;
- }
+ FfData ff_clr(ff.module, &initvals, NEW_ID);
+ ff_clr.width = ff.width;
+ ff_clr.has_aload = ff.has_aload;
+ ff_clr.sig_aload = ff.sig_aload;
+ ff_clr.pol_aload = ff.pol_aload;
+ ff_clr.sig_ad = ff.sig_ad;
+ ff_clr.has_clk = ff.has_clk;
+ ff_clr.sig_clk = ff.sig_clk;
+ ff_clr.pol_clk = ff.pol_clk;
+ ff_clr.sig_d = ff.sig_d;
+ ff_clr.has_ce = ff.has_ce;
+ ff_clr.sig_ce = ff.sig_ce;
+ ff_clr.pol_ce = ff.pol_ce;
+ ff_clr.has_arst = true;
+ ff_clr.sig_arst = ff.sig_clr;
+ ff_clr.pol_arst = ff.pol_clr;
+ ff_clr.val_arst = Const(State::S0, ff.width);
+ ff_clr.sig_q = ff.module->addWire(NEW_ID, ff.width);
+ ff_clr.val_init = init_clr ? ff.val_init : Const(State::Sx, ff.width);
+ ff_clr.is_fine = ff.is_fine;
- log_warning("Emulating async set + reset with several FFs and a mux for %s.%s\n", log_id(cell->module->name), log_id(cell->name));
- initvals.remove_init(sig_q[0]);
- Wire *adff0_q = cell->module->addWire(NEW_ID);
- Wire *adff1_q = cell->module->addWire(NEW_ID);
- Wire *sel_q = cell->module->addWire(NEW_ID);
- if (init0)
- initvals.set_init(SigBit(adff0_q, 0), initval);
- if (init1)
- initvals.set_init(SigBit(adff1_q, 0), initval);
- initvals.set_init(SigBit(sel_q, 0), initsel);
- Cell *cell_adff0;
- Cell *cell_adff1;
- Cell *cell_sel;
- if (ff_type == FF_DFFSR) {
- cell_adff0 = cell->module->addAdffGate(NEW_ID, sig_c, sig_r, sig_d, adff0_q, false, !(ff_neg & NEG_C), !(ff_neg & NEG_R));
- cell_adff1 = cell->module->addAdffGate(NEW_ID, sig_c, sig_s, sig_d, adff1_q, true, !(ff_neg & NEG_C), !(ff_neg & NEG_S));
- } else {
- cell_adff0 = cell->module->addAdffeGate(NEW_ID, sig_c, sig_e, sig_r, sig_d, adff0_q, false, !(ff_neg & NEG_C), !(ff_neg & NEG_E), !(ff_neg & NEG_R));
- cell_adff1 = cell->module->addAdffeGate(NEW_ID, sig_c, sig_e, sig_s, sig_d, adff1_q, true, !(ff_neg & NEG_C), !(ff_neg & NEG_E), !(ff_neg & NEG_S));
- }
- cell_sel = cell->module->addSrGate(NEW_ID, sig_s, sig_r, sel_q, !(ff_neg & NEG_S), !(ff_neg & NEG_R));
- cell->module->addMuxGate(NEW_ID, adff0_q, adff1_q, sel_q, sig_q);
-
- // Bye, cell.
- cell->module->remove(cell);
- handle_ff(cell_adff0);
- handle_ff(cell_adff1);
- handle_ff(cell_sel);
+ FfData ff_set(ff.module, &initvals, NEW_ID);
+ ff_set.width = ff.width;
+ ff_set.has_aload = ff.has_aload;
+ ff_set.sig_aload = ff.sig_aload;
+ ff_set.pol_aload = ff.pol_aload;
+ ff_set.sig_ad = ff.sig_ad;
+ ff_set.has_clk = ff.has_clk;
+ ff_set.sig_clk = ff.sig_clk;
+ ff_set.pol_clk = ff.pol_clk;
+ ff_set.sig_d = ff.sig_d;
+ ff_set.has_ce = ff.has_ce;
+ ff_set.sig_ce = ff.sig_ce;
+ ff_set.pol_ce = ff.pol_ce;
+ ff_set.has_arst = true;
+ ff_set.sig_arst = ff.sig_set;
+ ff_set.pol_arst = ff.pol_set;
+ ff_set.val_arst = Const(State::S1, ff.width);
+ ff_set.sig_q = ff.module->addWire(NEW_ID, ff.width);
+ ff_set.val_init = init_set ? ff.val_init : Const(State::Sx, ff.width);
+ ff_set.is_fine = ff.is_fine;
+
+ FfData ff_sel(ff.module, &initvals, NEW_ID);
+ ff_sel.width = ff.width;
+ ff_sel.has_sr = true;
+ ff_sel.pol_clr = ff.pol_clr;
+ ff_sel.pol_set = ff.pol_set;
+ ff_sel.sig_clr = ff.sig_clr;
+ ff_sel.sig_set = ff.sig_set;
+ ff_sel.sig_q = ff.module->addWire(NEW_ID, ff.width);
+ ff_sel.val_init = Const(initsel, ff.width);
+ ff_sel.is_fine = ff.is_fine;
+
+ if (!ff.is_fine)
+ ff.module->addMux(NEW_ID, ff_clr.sig_q, ff_set.sig_q, ff_sel.sig_q, ff.sig_q);
+ else
+ ff.module->addMuxGate(NEW_ID, ff_clr.sig_q, ff_set.sig_q, ff_sel.sig_q, ff.sig_q);
+
+ legalize_ff(ff_clr);
+ legalize_ff(ff_set);
+ legalize_ff(ff_sel);
+ }
+
+ void legalize_dff(FfData &ff) {
+ if (!try_flip(ff, supported_dff)) {
+ if (!supported_dff)
+ fail_ff(ff, "D flip-flops are not supported");
+ else
+ fail_ff(ff, "initialized D flip-flops are not supported");
+ }
+
+ int initmask = get_initmask(ff);
+ // Some DFF is supported with this init val. Just pick a type.
+ if (ff.has_ce && !(supported_dffe & initmask)) {
+ ff.unmap_ce();
+ }
+
+ if (!ff.has_ce) {
+ if (supported_cells[FF_DFF] & initmask) {
+ legalize_finish(ff);
return;
- } else if (ff_type == FF_SR) {
- if (supported_cells[FF_ADLATCH0] & initmask || supported_cells[FF_ADLATCH1] & flip_initmask(initmask)) {
- // Convert to ADLATCH0. May get converted to ADLATCH1.
- ff_type = FF_ADLATCH0;
- sig_e = sig_s;
- sig_d = State::S1;
- if (ff_neg & NEG_S) {
- ff_neg &= ~NEG_S;
- ff_neg |= NEG_E;
- }
- continue;
- } else if (supported_cells[FF_DLATCHSR] & initmask) {
- // Upgrade to DLATCHSR.
- ff_type = FF_DLATCHSR;
- sig_e = State::S0;
- sig_d = State::Sx;
- break;
- } else if (supported_dffsr & initmask) {
- // Upgrade to DFFSR. May get further upgraded to DFFSRE.
- ff_type = FF_DFFSR;
- sig_c = State::S0;
- sig_d = State::Sx;
- continue;
- } else if (supported_sr & flip_initmask(initmask)) {
- goto flip_dqisr;
- } else {
- if (!supported_sr)
- reason = "sr latches are not supported";
- else
- reason = "initialized sr latches are not supported";
- goto error;
- }
- } else if (ff_type == FF_DLATCH) {
- if (!(supported_dlatch & initmask)) {
- // This init value is not supported at all...
- if (supported_dlatch & flip_initmask(initmask))
- goto flip_dqi;
-
- if ((sig_d == State::S0 && (supported_adff0 & initmask)) ||
- (sig_d == State::S1 && (supported_adff1 & initmask)) ||
- (sig_d == State::S0 && (supported_adff1 & flip_initmask(initmask))) ||
- (sig_d == State::S1 && (supported_adff0 & flip_initmask(initmask)))
- ) {
- // Special case: const-D dlatch can be converted into adff with const clock.
- ff_type = (sig_d == State::S0) ? FF_ADFF0 : FF_ADFF1;
- if (ff_neg & NEG_E) {
- ff_neg &= ~NEG_E;
- ff_neg |= NEG_R;
- }
- sig_r = sig_e;
- sig_d = State::Sx;
- sig_c = State::S1;
- continue;
- }
+ }
+ // Try adding a set or reset pin.
+ if (supported_cells[FF_SDFF] & initmask) {
+ ff.add_dummy_srst();
+ legalize_finish(ff);
+ return;
+ }
+ if (supported_cells[FF_ADFF] & initmask) {
+ ff.add_dummy_arst();
+ legalize_finish(ff);
+ return;
+ }
+ // Try adding async load.
+ if (supported_cells[FF_ALDFF] & initmask) {
+ ff.add_dummy_aload();
+ legalize_finish(ff);
+ return;
+ }
+ // Try adding both.
+ if (supported_cells[FF_DFFSR] & initmask) {
+ ff.add_dummy_sr();
+ legalize_finish(ff);
+ return;
+ }
+ // Nope. Will need to add enable and go the DFFE route.
+ ff.add_dummy_ce();
+ }
+ if (supported_cells[FF_DFFE] & initmask) {
+ legalize_finish(ff);
+ return;
+ }
+ // Try adding a set or reset pin.
+ if (supported_cells[FF_SDFFCE] & initmask) {
+ ff.add_dummy_srst();
+ ff.ce_over_srst = true;
+ legalize_finish(ff);
+ return;
+ }
+ if (supported_cells[FF_SDFFE] & initmask) {
+ ff.add_dummy_srst();
+ legalize_finish(ff);
+ return;
+ }
+ if (supported_cells[FF_ADFFE] & initmask) {
+ ff.add_dummy_arst();
+ legalize_finish(ff);
+ return;
+ }
+ if (supported_cells[FF_ALDFFE] & initmask) {
+ ff.add_dummy_aload();
+ legalize_finish(ff);
+ return;
+ }
+ // Try adding both.
+ if (supported_cells[FF_DFFSRE] & initmask) {
+ ff.add_dummy_sr();
+ legalize_finish(ff);
+ return;
+ }
+ log_assert(0);
+ }
- if (!supported_dlatch)
- reason = "dlatch are not supported";
- else
- reason = "initialized dlatch are not supported";
- goto error;
- }
+ void legalize_sdffce(FfData &ff) {
+ if (!try_flip(ff, supported_cells[FF_SDFFCE] | supported_cells[FF_SDFFE])) {
+ ff.unmap_srst();
+ legalize_dff(ff);
+ return;
+ }
- // Some DLATCH is supported with this init val. Just pick a type.
- if (supported_cells[FF_ADLATCH0] & initmask) {
- ff_type = FF_ADLATCH0;
- sig_r = State::S0;
- break;
- }
- if (supported_cells[FF_ADLATCH1] & initmask) {
- ff_type = FF_ADLATCH1;
- sig_r = State::S0;
- break;
- }
- if (supported_cells[FF_DLATCHSR] & initmask) {
- ff_type = FF_DLATCHSR;
- sig_r = State::S0;
- sig_s = State::S0;
- break;
- }
+ int initmask = get_initmask(ff);
+ if (supported_cells[FF_SDFFCE] & initmask) {
+ // OK
+ } else if (supported_cells[FF_SDFFE] & initmask) {
+ ff.convert_ce_over_srst(false);
+ } else {
+ log_assert(0);
+ }
+ legalize_finish(ff);
+ }
+
+ void legalize_sdff(FfData &ff) {
+ if (!try_flip(ff, supported_sdff)) {
+ ff.unmap_srst();
+ legalize_dff(ff);
+ return;
+ }
+
+ int initmask = get_initmask(ff);
+ if (!ff.has_ce) {
+ if (supported_cells[FF_SDFF] & initmask) {
+ // OK
+ } else if (supported_cells[FF_SDFFE] & initmask) {
+ ff.add_dummy_ce();
+ } else if (supported_cells[FF_SDFFCE] & initmask) {
+ ff.add_dummy_ce();
+ ff.ce_over_srst = true;
+ } else {
log_assert(0);
- } else if (ff_type == FF_ADLATCH0 || ff_type == FF_ADLATCH1) {
- if (supported_cells[FF_DLATCHSR] & initmask) {
- if (ff_type == FF_ADLATCH1) {
- sig_s = sig_r;
- sig_r = State::S0;
- if (ff_neg & NEG_R) {
- ff_neg &= ~NEG_R;
- ff_neg |= NEG_S;
- }
- } else {
- sig_s = State::S0;
- }
- ff_type = FF_DLATCHSR;
- break;
- }
- FfType flip_type = ff_type == FF_ADLATCH0 ? FF_ADLATCH1 : FF_ADLATCH0;
- if ((supported_cells[flip_type] | supported_cells[FF_DLATCHSR]) & flip_initmask(initmask)) {
- ff_type = flip_type;
- goto flip_dqi;
- }
+ }
+ } else {
+ log_assert(!ff.ce_over_srst);
+ if (supported_cells[FF_SDFFE] & initmask) {
+ // OK
+ } else if (supported_cells[FF_SDFFCE] & initmask) {
+ ff.convert_ce_over_srst(true);
+ } else if (supported_cells[FF_SDFF] & initmask) {
+ ff.unmap_ce();
+ } else {
+ log_assert(0);
+ }
+ }
+ legalize_finish(ff);
+ }
- if (!supported_cells[FF_ADLATCH0] && !supported_cells[FF_ADLATCH1] && !supported_cells[FF_DLATCHSR]) {
- reason = "dlatch with async set or reset are not supported";
- goto error;
- }
- if (!(supported_dlatch & ~INIT_X)) {
- reason = "initialized dlatch are not supported";
- goto error;
- }
+ void legalize_adff(FfData &ff) {
+ if (!try_flip(ff, supported_adff)) {
+ if (!supported_adff)
+ fail_ff(ff, "dffs with async set or reset are not supported");
+ if (!(supported_dff & (INIT_0 | INIT_1)))
+ fail_ff(ff, "initialized dffs are not supported");
- if (!(supported_dlatch & ~INIT_X)) {
- reason = "initialized dlatch are not supported";
- goto error;
- }
- // If we got here, initialized dlatch is supported, but not this
- // particular reset+init combination (nor its negation).
- // The only hope left is breaking down to adff + dff + dlatch + mux.
-
- log_warning("Emulating mismatched async reset and init with several latches and a mux for %s.%s\n", log_id(cell->module->name), log_id(cell->name));
- initvals.remove_init(sig_q[0]);
- Wire *adlatch_q = cell->module->addWire(NEW_ID);
- Wire *dlatch_q = cell->module->addWire(NEW_ID);
- Wire *sel_q = cell->module->addWire(NEW_ID);
- initvals.set_init(SigBit(dlatch_q, 0), initval);
- initvals.set_init(SigBit(sel_q, 0), State::S0);
- Cell *cell_dlatch;
- Cell *cell_adlatch;
- Cell *cell_sel;
- cell_dlatch = cell->module->addDlatchGate(NEW_ID, sig_e, sig_d, dlatch_q, !(ff_neg & NEG_E));
- cell_adlatch = cell->module->addAdlatchGate(NEW_ID, sig_e, sig_r, sig_d, adlatch_q, ff_type == FF_ADLATCH1, !(ff_neg & NEG_E), !(ff_neg & NEG_R));
- cell_sel = cell->module->addDlatchGate(NEW_ID, sig_r, State::S1, sel_q, !(ff_neg & NEG_R));
- cell->module->addMuxGate(NEW_ID, dlatch_q, adlatch_q, sel_q, sig_q);
-
- // Bye, cell.
- cell->module->remove(cell);
- handle_ff(cell_dlatch);
- handle_ff(cell_adlatch);
- handle_ff(cell_sel);
+ // If we got here, initialized dff is supported, but not this
+ // particular reset+init combination (nor its negation).
+ // The only hope left is breaking down to adff + dff + dlatch + mux.
+
+ if (!((supported_rlatch) & (INIT_0_R1 | INIT_1_R0)))
+ fail_ff(ff, "unsupported initial value and async reset value combination");
+
+ // If we have to unmap enable anyway, do it before breakdown.
+ if (ff.has_ce && !supported_cells[FF_ADFFE])
+ ff.unmap_ce();
+
+ if (ff.cell)
+ log_warning("Emulating mismatched async reset and init with several FFs and a mux for %s.%s\n", log_id(ff.module->name), log_id(ff.cell->name));
+ emulate_split_init_arst(ff);
+ return;
+ }
+
+ int initmask = get_initmask(ff);
+ if (ff.has_ce && !(supported_adffe & initmask)) {
+ ff.unmap_ce();
+ }
+
+ if (!ff.has_ce) {
+ if (supported_cells[FF_ADFF] & initmask) {
+ legalize_finish(ff);
return;
- } else if (ff_type == FF_DLATCHSR) {
- if (supported_cells[FF_DLATCHSR] & flip_initmask(initmask)) {
- goto flip_dqisr;
- }
- // No native DFFSR. However, if we can conjure
- // a SR latch and ADFF, it can still be emulated.
- int flipmask = flip_initmask(initmask);
- bool init0 = true;
- bool init1 = true;
- State initsel = State::Sx;
- if (((supported_cells[FF_ADLATCH0] & initmask) || (supported_cells[FF_ADLATCH1] & flipmask)) && ((supported_cells[FF_ADLATCH1] & initmask) || (supported_cells[FF_ADLATCH0] & flipmask)) && supported_sr) {
- // OK
- } else if (((supported_cells[FF_ADLATCH0] & initmask) || (supported_cells[FF_ADLATCH1] & flipmask)) && (supported_sr & INIT_0)) {
- init1 = false;
- initsel = State::S0;
- } else if (((supported_cells[FF_ADLATCH1] & initmask) || (supported_cells[FF_ADLATCH0] & flipmask)) && (supported_sr & INIT_1)) {
- init0 = false;
- initsel = State::S1;
- } else if (((supported_cells[FF_ADLATCH0] & initmask) || (supported_cells[FF_ADLATCH1] & flipmask)) && (supported_sr & INIT_1)) {
- init1 = false;
- initsel = State::S0;
- } else if (((supported_cells[FF_ADLATCH1] & initmask) || (supported_cells[FF_ADLATCH0] & flipmask)) && (supported_sr & INIT_0)) {
- init0 = false;
- initsel = State::S1;
- } else {
- if (!supported_cells[FF_DLATCHSR])
- reason = "dlatch with async set and reset are not supported";
- else
- reason = "initialized dlatch with async set and reset are not supported";
- goto error;
- }
+ }
+ // Try converting to async load.
+ if (supported_cells[FF_ALDFF] & initmask) {
+ ff.arst_to_aload();
+ legalize_finish(ff);
+ return;
+ }
+ // Try convertint to SR.
+ if (supported_cells[FF_DFFSR] & initmask) {
+ ff.arst_to_sr();
+ legalize_finish(ff);
+ return;
+ }
+ ff.add_dummy_ce();
+ }
+ if (supported_cells[FF_ADFFE] & initmask) {
+ legalize_finish(ff);
+ return;
+ }
+ // Try converting to async load.
+ if (supported_cells[FF_ALDFFE] & initmask) {
+ ff.arst_to_aload();
+ legalize_finish(ff);
+ return;
+ }
+ // Try convertint to SR.
+ if (supported_cells[FF_DFFSRE] & initmask) {
+ ff.arst_to_sr();
+ legalize_finish(ff);
+ return;
+ }
+ log_assert(0);
+ }
+
+ void legalize_aldff(FfData &ff) {
+ if (!try_flip(ff, supported_aldff)) {
+ ff.aload_to_sr();
+ emulate_split_set_clr(ff);
+ return;
+ }
+
+ int initmask = get_initmask(ff);
+ if (ff.has_ce && !(supported_aldffe & initmask)) {
+ ff.unmap_ce();
+ }
- log_warning("Emulating async set + reset with several latches and a mux for %s.%s\n", log_id(cell->module->name), log_id(cell->name));
- initvals.remove_init(sig_q[0]);
- Wire *adlatch0_q = cell->module->addWire(NEW_ID);
- Wire *adlatch1_q = cell->module->addWire(NEW_ID);
- Wire *sel_q = cell->module->addWire(NEW_ID);
- if (init0)
- initvals.set_init(SigBit(adlatch0_q, 0), initval);
- if (init1)
- initvals.set_init(SigBit(adlatch1_q, 0), initval);
- initvals.set_init(SigBit(sel_q, 0), initsel);
- Cell *cell_adlatch0;
- Cell *cell_adlatch1;
- Cell *cell_sel;
- cell_adlatch0 = cell->module->addAdlatchGate(NEW_ID, sig_e, sig_r, sig_d, adlatch0_q, false, !(ff_neg & NEG_E), !(ff_neg & NEG_R));
- cell_adlatch1 = cell->module->addAdlatchGate(NEW_ID, sig_e, sig_s, sig_d, adlatch1_q, true, !(ff_neg & NEG_E), !(ff_neg & NEG_S));
- cell_sel = cell->module->addSrGate(NEW_ID, sig_s, sig_r, sel_q, !(ff_neg & NEG_S), !(ff_neg & NEG_R));
- cell->module->addMuxGate(NEW_ID, adlatch0_q, adlatch1_q, sel_q, sig_q);
-
- // Bye, cell.
- cell->module->remove(cell);
- handle_ff(cell_adlatch0);
- handle_ff(cell_adlatch1);
- handle_ff(cell_sel);
+ if (!ff.has_ce) {
+ if (supported_cells[FF_ALDFF] & initmask) {
+ legalize_finish(ff);
return;
- } else if (ff_type == FF_SDFF0 || ff_type == FF_SDFF1 || ff_type == FF_SDFFE0 || ff_type == FF_SDFFE1 || ff_type == FF_SDFFCE0 || ff_type == FF_SDFFCE1) {
- bool has_set = ff_type == FF_SDFF1 || ff_type == FF_SDFFE1 || ff_type == FF_SDFFCE1;
- bool has_en = ff_type == FF_SDFFE0 || ff_type == FF_SDFFE1;
- bool has_ce = ff_type == FF_SDFFCE0 || ff_type == FF_SDFFCE1;
-
- if (has_en) {
- if (kill_ce || kill_srst) {
- ff_type = has_set ? FF_SDFF1 : FF_SDFF0;
- goto unmap_enable;
- }
- } else if (has_ce) {
- if (kill_ce || kill_srst)
- goto unmap_srst;
- } else {
- log_assert(!kill_ce);
- if (kill_srst)
- goto unmap_srst;
- }
+ }
+ if (supported_cells[FF_DFFSR] & initmask) {
+ ff.aload_to_sr();
+ legalize_finish(ff);
+ return;
+ }
+ ff.add_dummy_ce();
+ }
+ if (supported_cells[FF_ALDFFE] & initmask) {
+ legalize_finish(ff);
+ return;
+ }
+ if (supported_cells[FF_DFFSRE] & initmask) {
+ ff.aload_to_sr();
+ legalize_finish(ff);
+ return;
+ }
+ log_assert(0);
+ }
- if (!has_ce) {
- if (!has_en && (supported_cells[has_set ? FF_SDFFE1 : FF_SDFFE0] & initmask)) {
- // Just add enable.
- sig_e = State::S1;
- ff_type = has_set ? FF_SDFFE1 : FF_SDFFE0;
- break;
- }
- if (!has_en && (supported_cells[has_set ? FF_SDFFCE1 : FF_SDFFCE0] & initmask)) {
- // Just add enable.
- sig_e = State::S1;
- ff_type = has_set ? FF_SDFFCE1 : FF_SDFFCE0;
- break;
- }
- if (has_en && (supported_cells[has_set ? FF_SDFFCE1 : FF_SDFFCE0] & initmask)) {
- // Convert sdffe to sdffce
- if (!(ff_neg & NEG_E)) {
- if (!(ff_neg & NEG_R))
- sig_e = cell->module->OrGate(NEW_ID, sig_e, sig_r);
- else
- sig_e = cell->module->OrnotGate(NEW_ID, sig_e, sig_r);
- } else {
- if (!(ff_neg & NEG_R))
- sig_e = cell->module->AndnotGate(NEW_ID, sig_e, sig_r);
- else
- sig_e = cell->module->AndGate(NEW_ID, sig_e, sig_r);
- }
- ff_type = has_set ? FF_SDFFCE1 : FF_SDFFCE0;
- break;
- }
- if (has_en && (supported_cells[has_set ? FF_SDFF1 : FF_SDFF0] & initmask)) {
- // Unmap enable.
- ff_type = has_set ? FF_SDFF1 : FF_SDFF0;
- goto unmap_enable;
- }
- log_assert(!((has_set ? supported_sdff1 : supported_sdff0) & initmask));
- } else {
- if ((has_set ? supported_sdff1 : supported_sdff0) & initmask) {
- // Convert sdffce to sdffe, which may be further converted to sdff.
- if (!(ff_neg & NEG_R)) {
- if (!(ff_neg & NEG_E))
- sig_r = cell->module->AndGate(NEW_ID, sig_r, sig_e);
- else
- sig_r = cell->module->AndnotGate(NEW_ID, sig_r, sig_e);
- } else {
- if (!(ff_neg & NEG_E))
- sig_r = cell->module->OrnotGate(NEW_ID, sig_r, sig_e);
- else
- sig_r = cell->module->OrGate(NEW_ID, sig_r, sig_e);
- }
- ff_type = has_set ? FF_SDFFE1 : FF_SDFFE0;
- continue;
- }
+ void legalize_dffsr(FfData &ff) {
+ if (!try_flip(ff, supported_dffsr)) {
+ emulate_split_set_clr(ff);
+ return;
+ }
+
+ int initmask = get_initmask(ff);
+ if (ff.has_ce && !(supported_cells[FF_DFFSRE] & initmask)) {
+ ff.unmap_ce();
+ }
+
+ if (!ff.has_ce) {
+ if (supported_cells[FF_DFFSR] & initmask) {
+ legalize_finish(ff);
+ return;
+ }
+ ff.add_dummy_ce();
+ }
+
+ log_assert(supported_cells[FF_DFFSRE] & initmask);
+ legalize_finish(ff);
+ }
+
+ void legalize_dlatch(FfData &ff) {
+ if (!try_flip(ff, supported_dlatch)) {
+ if (!supported_dlatch)
+ fail_ff(ff, "D latches are not supported");
+ else
+ fail_ff(ff, "initialized D latches are not supported");
+ }
+
+ int initmask = get_initmask(ff);
+ // Some DLATCH is supported with this init val. Just pick a type.
+ if (supported_cells[FF_DLATCH] & initmask) {
+ legalize_finish(ff);
+ } else if (supported_cells[FF_ADLATCH] & initmask) {
+ ff.add_dummy_arst();
+ legalize_finish(ff);
+ } else if (supported_cells[FF_DLATCHSR] & initmask) {
+ ff.add_dummy_sr();
+ legalize_finish(ff);
+ } else if (supported_cells[FF_ALDFF] & initmask) {
+ ff.add_dummy_clk();
+ legalize_finish(ff);
+ } else if (supported_cells[FF_ALDFFE] & initmask) {
+ ff.add_dummy_clk();
+ ff.add_dummy_ce();
+ legalize_finish(ff);
+ } else if (supported_sr & initmask) {
+ ff.aload_to_sr();
+ legalize_sr(ff);
+ } else {
+ log_assert(0);
+ }
+ }
+
+ void legalize_adlatch(FfData &ff) {
+ if (!try_flip(ff, supported_adlatch)) {
+ if (!supported_adlatch)
+ fail_ff(ff, "D latches with async set or reset are not supported");
+ if (!(supported_dlatch & (INIT_0 | INIT_1)))
+ fail_ff(ff, "initialized D latches are not supported");
+
+ // If we got here, initialized dlatch is supported, but not this
+ // particular reset+init combination (nor its negation).
+ // The only hope left is breaking down to adlatch + dlatch + dlatch + mux.
+
+ if (ff.cell)
+ log_warning("Emulating mismatched async reset and init with several latches and a mux for %s.%s\n", log_id(ff.module->name), log_id(ff.cell->name));
+ ff.remove();
+
+ emulate_split_init_arst(ff);
+ return;
+ }
+ int initmask = get_initmask(ff);
+ if (supported_cells[FF_ADLATCH] & initmask) {
+ // OK
+ } else if (supported_cells[FF_DLATCHSR] & initmask) {
+ ff.arst_to_sr();
+ } else {
+ log_assert(0);
+ }
+ legalize_finish(ff);
+ }
+
+ void legalize_dlatchsr(FfData &ff) {
+ if (!try_flip(ff, supported_cells[FF_DLATCHSR])) {
+ emulate_split_set_clr(ff);
+ return;
+ }
+ legalize_finish(ff);
+ }
+
+ void legalize_rlatch(FfData &ff) {
+ if (!try_flip(ff, supported_rlatch)) {
+ if (!supported_dlatch)
+ fail_ff(ff, "D latches are not supported");
+ else
+ fail_ff(ff, "initialized D latches are not supported");
+ }
+
+ int initmask = get_initmask(ff);
+ if (((supported_dlatch_plain & 7) * 0x111) & initmask) {
+ ff.arst_to_aload();
+ legalize_dlatch(ff);
+ } else if (supported_sr & initmask) {
+ ff.arst_to_sr();
+ legalize_sr(ff);
+ } else if (supported_adff & initmask) {
+ ff.add_dummy_clk();
+ legalize_adff(ff);
+ } else {
+ log_assert(0);
+ }
+ }
+
+ void legalize_sr(FfData &ff) {
+ if (!try_flip(ff, supported_sr)) {
+ if (!supported_sr)
+ fail_ff(ff, "sr latches are not supported");
+ else
+ fail_ff(ff, "initialized sr latches are not supported");
+ }
+ int initmask = get_initmask(ff);
+ if (supported_cells[FF_SR] & initmask) {
+ // OK
+ } else if (supported_cells[FF_DLATCHSR] & initmask) {
+ // Upgrade to DLATCHSR.
+ ff.add_dummy_aload();
+ } else if (supported_cells[FF_DFFSR] & initmask) {
+ // Upgrade to DFFSR.
+ ff.add_dummy_clk();
+ } else if (supported_cells[FF_DFFSRE] & initmask) {
+ // Upgrade to DFFSRE.
+ ff.add_dummy_clk();
+ ff.add_dummy_ce();
+ } else if (supported_cells[FF_ADLATCH] & (initmask << 4)) {
+ ff.has_sr = false;
+ ff.has_aload = true;
+ ff.has_arst = true;
+ ff.pol_arst = ff.pol_clr;
+ ff.sig_arst = ff.sig_clr;
+ ff.sig_aload = ff.sig_set;
+ ff.pol_aload = ff.pol_set;
+ ff.sig_ad = State::S1;
+ ff.val_arst = State::S0;
+ } else if (supported_cells[FF_ADLATCH] & (flip_initmask(initmask) << 8)) {
+ ff.has_sr = false;
+ ff.has_aload = true;
+ ff.has_arst = true;
+ ff.pol_arst = ff.pol_clr;
+ ff.sig_arst = ff.sig_clr;
+ ff.sig_aload = ff.sig_set;
+ ff.pol_aload = ff.pol_set;
+ ff.sig_ad = State::S0;
+ ff.val_arst = State::S1;
+ ff.remove_init();
+ Wire *new_q = ff.module->addWire(NEW_ID);
+ if (ff.is_fine)
+ ff.module->addNotGate(NEW_ID, new_q, ff.sig_q);
+ else
+ ff.module->addNot(NEW_ID, new_q, ff.sig_q);
+ ff.sig_q = new_q;
+ if (ff.val_init == State::S0)
+ ff.val_init = State::S1;
+ else if (ff.val_init == State::S1)
+ ff.val_init = State::S0;
+ } else {
+ log_assert(0);
+ }
+ legalize_finish(ff);
+ }
+
+ void fixup_reset_x(FfData &ff, int supported) {
+ for (int i = 0; i < ff.width; i++) {
+ int mask;
+ if (ff.val_init[i] == State::S0)
+ mask = INIT_0;
+ else if (ff.val_init[i] == State::S1)
+ mask = INIT_1;
+ else
+ mask = INIT_X;
+ if (ff.has_arst) {
+ if (ff.val_arst[i] == State::Sx) {
+ if (!(supported & (mask << 8)))
+ ff.val_arst[i] = State::S0;
+ if (!(supported & (mask << 4)))
+ ff.val_arst[i] = State::S1;
}
- // Alright, so this particular combination of initval and
- // resetval is not natively supported. First, try flipping
- // them both to see whether this helps.
- if ((has_set ? supported_sdff0 : supported_sdff1) & flip_initmask(initmask)) {
- // Checks out, do it.
- ff_type = has_ce ? (has_set ? FF_SDFFCE0 : FF_SDFFCE1) : has_en ? (has_set ? FF_SDFFE0 : FF_SDFFE1) : (has_set ? FF_SDFF0 : FF_SDFF1);
- goto flip_dqi;
+ }
+ if (ff.has_srst) {
+ if (ff.val_srst[i] == State::Sx) {
+ if (!(supported & (mask << 8)))
+ ff.val_srst[i] = State::S0;
+ if (!(supported & (mask << 4)))
+ ff.val_srst[i] = State::S1;
}
+ }
+ }
+ }
- // Nope. No way to get SDFF* of the right kind, so unmap it.
- // For SDFFE, the enable has to be unmapped first.
- if (has_en) {
- ff_type = has_set ? FF_SDFF1 : FF_SDFF0;
- goto unmap_enable;
- }
-unmap_srst:
- if (has_ce)
- ff_type = FF_DFFE;
- else
- ff_type = FF_DFF;
- if (ff_neg & NEG_R)
- sig_d = cell->module->MuxGate(NEW_ID, has_set ? State::S1 : State::S0, sig_d[0], sig_r[0]);
+ void legalize_ff(FfData &ff) {
+ if (ff.has_gclk)
+ return;
+
+ // TODO: consider supporting coarse as well.
+ if (!ff.is_fine)
+ return;
+
+ if (mince && ff.has_ce && ff.sig_ce[0].wire && ce_used[ff.sig_ce[0]] < mince)
+ ff.unmap_ce();
+ if (minsrst && ff.has_srst && ff.sig_srst[0].wire && srst_used[ff.sig_srst[0]] < minsrst)
+ ff.unmap_srst();
+
+ if (ff.has_clk) {
+ if (ff.has_sr) {
+ legalize_dffsr(ff);
+ } else if (ff.has_aload) {
+ legalize_aldff(ff);
+ } else if (ff.has_arst) {
+ legalize_adff(ff);
+ } else if (ff.has_srst) {
+ if (ff.has_ce && ff.ce_over_srst)
+ legalize_sdffce(ff);
else
- sig_d = cell->module->MuxGate(NEW_ID, sig_d[0], has_set ? State::S1 : State::S0, sig_r[0]);
- ff_neg &= ~NEG_R;
- sig_r = SigSpec();
- kill_srst = false;
- continue;
+ legalize_sdff(ff);
+ } else {
+ legalize_dff(ff);
+ }
+ } else if (ff.has_aload) {
+ if (ff.has_sr) {
+ legalize_dlatchsr(ff);
+ } else if (ff.has_arst) {
+ legalize_adlatch(ff);
+ } else {
+ legalize_dlatch(ff);
+ }
+ } else {
+ if (ff.has_sr) {
+ legalize_sr(ff);
+ } else if (ff.has_arst) {
+ legalize_rlatch(ff);
} else {
log_assert(0);
}
}
-cell_ok:
+ }
+
+ void flip_pol(FfData &ff, SigSpec &sig, bool &pol) {
+ if (sig == State::S0) {
+ sig = State::S1;
+ } else if (sig == State::S1) {
+ sig = State::S0;
+ } else if (ff.is_fine) {
+ sig = ff.module->NotGate(NEW_ID, sig);
+ } else {
+ sig = ff.module->Not(NEW_ID, sig);
+ }
+ pol = !pol;
+ }
+ void legalize_finish(FfData &ff) {
+ int ff_type = get_ff_type(ff);
+ int initmask = get_initmask(ff);
+ log_assert(supported_cells[ff_type] & initmask);
+ int ff_neg = 0;
+ if (ff.has_sr) {
+ if (!ff.pol_clr)
+ ff_neg |= NEG_R;
+ if (!ff.pol_set)
+ ff_neg |= NEG_S;
+ }
+ if (ff.has_arst) {
+ if (!ff.pol_arst)
+ ff_neg |= NEG_R;
+ }
+ if (ff.has_srst) {
+ if (!ff.pol_srst)
+ ff_neg |= NEG_R;
+ }
+ if (ff.has_aload) {
+ if (!ff.pol_aload)
+ ff_neg |= NEG_L;
+ }
+ if (ff.has_clk) {
+ if (!ff.pol_clk)
+ ff_neg |= NEG_C;
+ }
+ if (ff.has_ce) {
+ if (!ff.pol_ce)
+ ff_neg |= NEG_CE;
+ }
if (!(supported_cells_neg[ff_type][ff_neg] & initmask)) {
// Cell is supported, but not with those polarities.
// Will need to add some inverters.
@@ -921,182 +998,27 @@ cell_ok:
if (supported_cells_neg[ff_type][ff_neg ^ xneg] & initmask)
break;
log_assert(xneg < NUM_NEG);
- if (xneg & NEG_R)
- sig_r = cell->module->NotGate(NEW_ID, sig_r[0]);
- if (xneg & NEG_S)
- sig_s = cell->module->NotGate(NEW_ID, sig_s[0]);
- if (xneg & NEG_E)
- sig_e = cell->module->NotGate(NEW_ID, sig_e[0]);
+ if (xneg & NEG_CE)
+ flip_pol(ff, ff.sig_ce, ff.pol_ce);
+ if (ff.has_sr) {
+ if (xneg & NEG_R)
+ flip_pol(ff, ff.sig_clr, ff.pol_clr);
+ if (xneg & NEG_S)
+ flip_pol(ff, ff.sig_set, ff.pol_set);
+ }
+ if (ff.has_arst && xneg & NEG_R)
+ flip_pol(ff, ff.sig_arst, ff.pol_arst);
+ if (ff.has_srst && xneg & NEG_R)
+ flip_pol(ff, ff.sig_srst, ff.pol_srst);
+ if (xneg & NEG_L)
+ flip_pol(ff, ff.sig_aload, ff.pol_aload);
if (xneg & NEG_C)
- sig_c = cell->module->NotGate(NEW_ID, sig_c[0]);
+ flip_pol(ff, ff.sig_clk, ff.pol_clk);
ff_neg ^= xneg;
}
- cell->unsetPort(ID::D);
- cell->unsetPort(ID::Q);
- cell->unsetPort(ID::C);
- cell->unsetPort(ID::E);
- cell->unsetPort(ID::S);
- cell->unsetPort(ID::R);
- switch (ff_type) {
- case FF_DFF:
- cell->type = IdString(stringf("$_DFF_%c_",
- (ff_neg & NEG_C) ? 'N' : 'P'
- ));
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, sig_q);
- cell->setPort(ID::C, sig_c);
- break;
- case FF_DFFE:
- cell->type = IdString(stringf("$_DFFE_%c%c_",
- (ff_neg & NEG_C) ? 'N' : 'P',
- (ff_neg & NEG_E) ? 'N' : 'P'
- ));
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, sig_q);
- cell->setPort(ID::C, sig_c);
- cell->setPort(ID::E, sig_e);
- break;
- case FF_ADFF0:
- case FF_ADFF1:
- cell->type = IdString(stringf("$_DFF_%c%c%c_",
- (ff_neg & NEG_C) ? 'N' : 'P',
- (ff_neg & NEG_R) ? 'N' : 'P',
- (ff_type == FF_ADFF1) ? '1' : '0'
- ));
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, sig_q);
- cell->setPort(ID::C, sig_c);
- cell->setPort(ID::R, sig_r);
- break;
- case FF_ADFFE0:
- case FF_ADFFE1:
- cell->type = IdString(stringf("$_DFFE_%c%c%c%c_",
- (ff_neg & NEG_C) ? 'N' : 'P',
- (ff_neg & NEG_R) ? 'N' : 'P',
- (ff_type == FF_ADFFE1) ? '1' : '0',
- (ff_neg & NEG_E) ? 'N' : 'P'
- ));
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, sig_q);
- cell->setPort(ID::C, sig_c);
- cell->setPort(ID::E, sig_e);
- cell->setPort(ID::R, sig_r);
- break;
- case FF_DFFSR:
- cell->type = IdString(stringf("$_DFFSR_%c%c%c_",
- (ff_neg & NEG_C) ? 'N' : 'P',
- (ff_neg & NEG_S) ? 'N' : 'P',
- (ff_neg & NEG_R) ? 'N' : 'P'
- ));
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, sig_q);
- cell->setPort(ID::C, sig_c);
- cell->setPort(ID::S, sig_s);
- cell->setPort(ID::R, sig_r);
- break;
- case FF_DFFSRE:
- cell->type = IdString(stringf("$_DFFSRE_%c%c%c%c_",
- (ff_neg & NEG_C) ? 'N' : 'P',
- (ff_neg & NEG_S) ? 'N' : 'P',
- (ff_neg & NEG_R) ? 'N' : 'P',
- (ff_neg & NEG_E) ? 'N' : 'P'
- ));
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, sig_q);
- cell->setPort(ID::C, sig_c);
- cell->setPort(ID::E, sig_e);
- cell->setPort(ID::S, sig_s);
- cell->setPort(ID::R, sig_r);
- break;
- case FF_SDFF0:
- case FF_SDFF1:
- cell->type = IdString(stringf("$_SDFF_%c%c%c_",
- (ff_neg & NEG_C) ? 'N' : 'P',
- (ff_neg & NEG_R) ? 'N' : 'P',
- (ff_type == FF_SDFF1) ? '1' : '0'
- ));
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, sig_q);
- cell->setPort(ID::C, sig_c);
- cell->setPort(ID::R, sig_r);
- break;
- case FF_SDFFE0:
- case FF_SDFFE1:
- cell->type = IdString(stringf("$_SDFFE_%c%c%c%c_",
- (ff_neg & NEG_C) ? 'N' : 'P',
- (ff_neg & NEG_R) ? 'N' : 'P',
- (ff_type == FF_SDFFE1) ? '1' : '0',
- (ff_neg & NEG_E) ? 'N' : 'P'
- ));
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, sig_q);
- cell->setPort(ID::C, sig_c);
- cell->setPort(ID::E, sig_e);
- cell->setPort(ID::R, sig_r);
- break;
- case FF_SDFFCE0:
- case FF_SDFFCE1:
- cell->type = IdString(stringf("$_SDFFCE_%c%c%c%c_",
- (ff_neg & NEG_C) ? 'N' : 'P',
- (ff_neg & NEG_R) ? 'N' : 'P',
- (ff_type == FF_SDFFCE1) ? '1' : '0',
- (ff_neg & NEG_E) ? 'N' : 'P'
- ));
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, sig_q);
- cell->setPort(ID::C, sig_c);
- cell->setPort(ID::E, sig_e);
- cell->setPort(ID::R, sig_r);
- break;
- case FF_DLATCH:
- cell->type = IdString(stringf("$_DLATCH_%c_",
- (ff_neg & NEG_E) ? 'N' : 'P'
- ));
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, sig_q);
- cell->setPort(ID::E, sig_e);
- break;
- case FF_ADLATCH0:
- case FF_ADLATCH1:
- cell->type = IdString(stringf("$_DLATCH_%c%c%c_",
- (ff_neg & NEG_E) ? 'N' : 'P',
- (ff_neg & NEG_R) ? 'N' : 'P',
- (ff_type == FF_ADLATCH1) ? '1' : '0'
- ));
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, sig_q);
- cell->setPort(ID::E, sig_e);
- cell->setPort(ID::R, sig_r);
- break;
- case FF_DLATCHSR:
- cell->type = IdString(stringf("$_DLATCHSR_%c%c%c_",
- (ff_neg & NEG_E) ? 'N' : 'P',
- (ff_neg & NEG_S) ? 'N' : 'P',
- (ff_neg & NEG_R) ? 'N' : 'P'
- ));
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, sig_q);
- cell->setPort(ID::E, sig_e);
- cell->setPort(ID::S, sig_s);
- cell->setPort(ID::R, sig_r);
- break;
- case FF_SR:
- cell->type = IdString(stringf("$_SR_%c%c_",
- (ff_neg & NEG_S) ? 'N' : 'P',
- (ff_neg & NEG_R) ? 'N' : 'P'
- ));
- cell->setPort(ID::Q, sig_q);
- cell->setPort(ID::S, sig_s);
- cell->setPort(ID::R, sig_r);
- break;
- default:
- log_assert(0);
- }
- return;
-
-error:
- log_error("FF %s.%s (type %s) cannot be legalized: %s\n", log_id(cell->module->name), log_id(cell->name), log_id(cell->type), reason);
+ fixup_reset_x(ff, supported_cells_neg[ff_type][ff_neg]);
+ ff.emit();
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -1118,79 +1040,83 @@ error:
if (args[argidx] == "-cell" && argidx + 2 < args.size()) {
std::string celltype = args[++argidx];
std::string inittype = args[++argidx];
- enum FfType ff_type[2] = {NUM_FFTYPES, NUM_FFTYPES};
+ enum FfType ff_type;
char pol_c = 0;
- char pol_e = 0;
+ char pol_l = 0;
char pol_s = 0;
char pol_r = 0;
+ char pol_ce = 0;
char srval = 0;
if (celltype.substr(0, 5) == "$_SR_" && celltype.size() == 8 && celltype[7] == '_') {
- ff_type[0] = FF_SR;
+ ff_type = FF_SR;
pol_s = celltype[5];
pol_r = celltype[6];
} else if (celltype.substr(0, 6) == "$_DFF_" && celltype.size() == 8 && celltype[7] == '_') {
- ff_type[0] = FF_DFF;
+ ff_type = FF_DFF;
pol_c = celltype[6];
} else if (celltype.substr(0, 7) == "$_DFFE_" && celltype.size() == 10 && celltype[9] == '_') {
- ff_type[0] = FF_DFFE;
+ ff_type = FF_DFFE;
pol_c = celltype[7];
- pol_e = celltype[8];
+ pol_ce = celltype[8];
} else if (celltype.substr(0, 6) == "$_DFF_" && celltype.size() == 10 && celltype[9] == '_') {
- ff_type[0] = FF_ADFF0;
- ff_type[1] = FF_ADFF1;
+ ff_type = FF_ADFF;
pol_c = celltype[6];
pol_r = celltype[7];
srval = celltype[8];
} else if (celltype.substr(0, 7) == "$_DFFE_" && celltype.size() == 12 && celltype[11] == '_') {
- ff_type[0] = FF_ADFFE0;
- ff_type[1] = FF_ADFFE1;
+ ff_type = FF_ADFFE;
pol_c = celltype[7];
pol_r = celltype[8];
srval = celltype[9];
- pol_e = celltype[10];
+ pol_ce = celltype[10];
+ } else if (celltype.substr(0, 8) == "$_ALDFF_" && celltype.size() == 11 && celltype[10] == '_') {
+ ff_type = FF_ALDFF;
+ pol_c = celltype[8];
+ pol_l = celltype[9];
+ } else if (celltype.substr(0, 9) == "$_ALDFFE_" && celltype.size() == 13 && celltype[12] == '_') {
+ ff_type = FF_ALDFFE;
+ pol_c = celltype[9];
+ pol_l = celltype[10];
+ pol_ce = celltype[11];
} else if (celltype.substr(0, 8) == "$_DFFSR_" && celltype.size() == 12 && celltype[11] == '_') {
- ff_type[0] = FF_DFFSR;
+ ff_type = FF_DFFSR;
pol_c = celltype[8];
pol_s = celltype[9];
pol_r = celltype[10];
} else if (celltype.substr(0, 9) == "$_DFFSRE_" && celltype.size() == 14 && celltype[13] == '_') {
- ff_type[0] = FF_DFFSRE;
+ ff_type = FF_DFFSRE;
pol_c = celltype[9];
pol_s = celltype[10];
pol_r = celltype[11];
- pol_e = celltype[12];
+ pol_ce = celltype[12];
} else if (celltype.substr(0, 7) == "$_SDFF_" && celltype.size() == 11 && celltype[10] == '_') {
- ff_type[0] = FF_SDFF0;
- ff_type[1] = FF_SDFF1;
+ ff_type = FF_SDFF;
pol_c = celltype[7];
pol_r = celltype[8];
srval = celltype[9];
} else if (celltype.substr(0, 8) == "$_SDFFE_" && celltype.size() == 13 && celltype[12] == '_') {
- ff_type[0] = FF_SDFFE0;
- ff_type[1] = FF_SDFFE1;
+ ff_type = FF_SDFFE;
pol_c = celltype[8];
pol_r = celltype[9];
srval = celltype[10];
- pol_e = celltype[11];
+ pol_ce = celltype[11];
} else if (celltype.substr(0, 9) == "$_SDFFCE_" && celltype.size() == 14 && celltype[13] == '_') {
- ff_type[0] = FF_SDFFCE0;
- ff_type[1] = FF_SDFFCE1;
+ ff_type = FF_SDFFCE;
pol_c = celltype[9];
pol_r = celltype[10];
srval = celltype[11];
- pol_e = celltype[12];
+ pol_ce = celltype[12];
} else if (celltype.substr(0, 9) == "$_DLATCH_" && celltype.size() == 11 && celltype[10] == '_') {
- ff_type[0] = FF_DLATCH;
- pol_e = celltype[9];
+ ff_type = FF_DLATCH;
+ pol_l = celltype[9];
} else if (celltype.substr(0, 9) == "$_DLATCH_" && celltype.size() == 13 && celltype[12] == '_') {
- ff_type[0] = FF_ADLATCH0;
- ff_type[1] = FF_ADLATCH1;
- pol_e = celltype[9];
+ ff_type = FF_ADLATCH;
+ pol_l = celltype[9];
pol_r = celltype[10];
srval = celltype[11];
} else if (celltype.substr(0, 11) == "$_DLATCHSR_" && celltype.size() == 15 && celltype[14] == '_') {
- ff_type[0] = FF_DLATCHSR;
- pol_e = celltype[11];
+ ff_type = FF_DLATCHSR;
+ pol_l = celltype[11];
pol_s = celltype[12];
pol_r = celltype[13];
} else {
@@ -1201,9 +1127,10 @@ unrecognized:
int match = 0;
for (auto pair : {
std::make_pair(pol_c, NEG_C),
- std::make_pair(pol_e, NEG_E),
+ std::make_pair(pol_l, NEG_L),
std::make_pair(pol_s, NEG_S),
std::make_pair(pol_r, NEG_R),
+ std::make_pair(pol_ce, NEG_CE),
}) {
if (pair.first == 'N') {
mask |= pair.second;
@@ -1214,40 +1141,33 @@ unrecognized:
goto unrecognized;
}
}
+ int initmask;
+ if (inittype == "x") {
+ initmask = 0x111;
+ } else if (inittype == "0") {
+ initmask = 0x333;
+ } else if (inittype == "1") {
+ initmask = 0x555;
+ } else if (inittype == "r") {
+ if (srval == 0)
+ log_error("init type r not valid for cell type %s.\n", celltype.c_str());
+ initmask = 0x537;
+ } else if (inittype == "01") {
+ initmask = 0x777;
+ } else {
+ log_error("unrecognized init type %s for cell type %s.\n", inittype.c_str(), celltype.c_str());
+ }
if (srval == '0') {
- ff_type[1] = NUM_FFTYPES;
+ initmask &= 0x0ff;
} else if (srval == '1') {
- ff_type[0] = NUM_FFTYPES;
+ initmask &= 0xf0f;
} else if (srval != 0 && srval != '?') {
goto unrecognized;
}
- for (int i = 0; i < 2; i++) {
- if (ff_type[i] == NUM_FFTYPES)
- continue;
- int initmask;
- if (inittype == "x") {
- initmask = INIT_X;
- } else if (inittype == "0") {
- initmask = INIT_X | INIT_0;
- } else if (inittype == "1") {
- initmask = INIT_X | INIT_1;
- } else if (inittype == "r") {
- if (srval == 0)
- log_error("init type r not valid for cell type %s.\n", celltype.c_str());
- if (i == 0)
- initmask = INIT_X | INIT_0;
- else
- initmask = INIT_X | INIT_1;
- } else if (inittype == "01") {
- initmask = INIT_X | INIT_0 | INIT_1;
- } else {
- log_error("unrecognized init type %s for cell type %s.\n", inittype.c_str(), celltype.c_str());
- }
- for (int neg = 0; neg < NUM_NEG; neg++)
- if ((neg & mask) == match)
- supported_cells_neg[ff_type[i]][neg] |= initmask;
- supported_cells[ff_type[i]] |= initmask;
- }
+ for (int neg = 0; neg < NUM_NEG; neg++)
+ if ((neg & mask) == match)
+ supported_cells_neg[ff_type][neg] |= initmask;
+ supported_cells[ff_type] |= initmask;
continue;
} else if (args[argidx] == "-mince" && argidx + 1 < args.size()) {
mince = atoi(args[++argidx].c_str());
@@ -1260,13 +1180,21 @@ unrecognized:
}
extra_args(args, argidx, design);
supported_dffsr = supported_cells[FF_DFFSR] | supported_cells[FF_DFFSRE];
- supported_adff0 = supported_cells[FF_ADFF0] | supported_cells[FF_ADFFE0] | supported_dffsr;
- supported_adff1 = supported_cells[FF_ADFF1] | supported_cells[FF_ADFFE1] | supported_dffsr;
- supported_sdff0 = supported_cells[FF_SDFF0] | supported_cells[FF_SDFFE0] | supported_cells[FF_SDFFCE0];
- supported_sdff1 = supported_cells[FF_SDFF1] | supported_cells[FF_SDFFE1] | supported_cells[FF_SDFFCE1];
- supported_dff = supported_cells[FF_DFF] | supported_cells[FF_DFFE] | supported_dffsr | supported_adff0 | supported_adff1 | supported_sdff0 | supported_sdff1;
- supported_sr = supported_dffsr | supported_cells[FF_DLATCHSR] | supported_cells[FF_SR] | supported_cells[FF_ADLATCH0] | flip_initmask(supported_cells[FF_ADLATCH1]);
- supported_dlatch = supported_cells[FF_DLATCH] | supported_cells[FF_ADLATCH0] | supported_cells[FF_ADLATCH1] | supported_cells[FF_DLATCHSR];
+ supported_aldff = supported_cells[FF_ALDFF] | supported_cells[FF_ALDFFE] | supported_dffsr;
+ supported_aldffe = supported_cells[FF_ALDFFE] | supported_cells[FF_DFFSRE];
+ supported_adff = supported_cells[FF_ADFF] | supported_cells[FF_ADFFE] | supported_dffsr | supported_aldff;
+ supported_adffe = supported_cells[FF_ADFFE] | supported_cells[FF_ALDFFE] | supported_cells[FF_DFFSRE];
+ supported_sdff = supported_cells[FF_SDFF] | supported_cells[FF_SDFFE] | supported_cells[FF_SDFFCE];
+ supported_dff = supported_cells[FF_DFF] | supported_cells[FF_DFFE] | supported_adff | supported_sdff;
+ supported_dffe = supported_cells[FF_DFFE] | supported_cells[FF_DFFSRE] | supported_cells[FF_ALDFFE] | supported_cells[FF_ADFFE] | supported_cells[FF_SDFFE] | supported_cells[FF_SDFFCE];
+ supported_sr_plain = supported_dffsr | supported_cells[FF_DLATCHSR] | supported_cells[FF_SR];
+ supported_sr = supported_sr_plain;
+ supported_sr |= (supported_cells[FF_ADLATCH] >> 4 & 7) * 0x111;
+ supported_sr |= (flip_initmask(supported_cells[FF_ADLATCH]) >> 4 & 7) * 0x111;
+ supported_dlatch_plain = supported_cells[FF_DLATCH] | supported_cells[FF_ADLATCH] | supported_cells[FF_DLATCHSR] | supported_cells[FF_ALDFF] | supported_cells[FF_ALDFFE];
+ supported_dlatch = supported_dlatch_plain | supported_sr_plain;
+ supported_rlatch = supported_adff | (supported_dlatch & 7) * 0x111;
+ supported_adlatch = supported_cells[FF_ADLATCH] | supported_cells[FF_DLATCHSR];
for (auto module : design->selected_modules())
{
@@ -1281,36 +1209,20 @@ unrecognized:
if (!RTLIL::builtin_ff_cell_types().count(cell->type))
continue;
- if (cell->hasPort(ID::C) && cell->hasPort(ID::E)) {
- SigSpec sig = cell->getPort(ID::E);
- // Do not count const enable signals.
- if (GetSize(sig) == 1 && sig[0].wire)
- ce_used[sig[0]]++;
- }
- if (cell->type.str().substr(0, 6) == "$_SDFF") {
- SigSpec sig = cell->getPort(ID::R);
- // Do not count const srst signals.
- if (GetSize(sig) == 1 && sig[0].wire)
- srst_used[sig[0]]++;
- }
+ FfData ff(&initvals, cell);
+ if (ff.has_ce && ff.sig_ce[0].wire)
+ ce_used[ff.sig_ce[0]] += ff.width;
+ if (ff.has_srst && ff.sig_srst[0].wire)
+ srst_used[ff.sig_srst[0]] += ff.width;
}
}
-
- // First gather FF cells, then iterate over them later.
- // We may need to split an FF into several cells.
- std::vector<Cell *> ff_cells;
-
for (auto cell : module->selected_cells())
{
- // Early exit for non-FFs.
if (!RTLIL::builtin_ff_cell_types().count(cell->type))
continue;
-
- ff_cells.push_back(cell);
+ FfData ff(&initvals, cell);
+ legalize_ff(ff);
}
-
- for (auto cell: ff_cells)
- handle_ff(cell);
}
sigmap.clear();
diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc
index 78a6f1c0d..252baae9a 100644
--- a/passes/techmap/dfflibmap.cc
+++ b/passes/techmap/dfflibmap.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/dffunmap.cc b/passes/techmap/dffunmap.cc
index fb107ff75..7312015f1 100644
--- a/passes/techmap/dffunmap.cc
+++ b/passes/techmap/dffunmap.cc
@@ -84,21 +84,20 @@ struct DffunmapPass : public Pass {
continue;
if (ce_only) {
- if (!ff.has_en)
+ if (!ff.has_ce)
continue;
- ff.unmap_ce(mod);
+ ff.unmap_ce();
} else if (srst_only) {
if (!ff.has_srst)
continue;
- ff.unmap_srst(mod);
+ ff.unmap_srst();
} else {
- if (!ff.has_en && !ff.has_srst)
+ if (!ff.has_ce && !ff.has_srst)
continue;
- ff.unmap_ce_srst(mod);
+ ff.unmap_ce_srst();
}
- mod->remove(cell);
- ff.emit(mod, name);
+ ff.emit();
}
}
}
diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc
index f5966fac0..137d22170 100644
--- a/passes/techmap/extract.cc
+++ b/passes/techmap/extract.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -74,6 +74,7 @@ public:
param_int(ID::CTRL_IN_WIDTH)
param_int(ID::CTRL_OUT_WIDTH)
param_int(ID::OFFSET)
+ param_int(ID::PORTID)
param_int(ID::PRIORITY)
param_int(ID::RD_PORTS)
param_int(ID::SIZE)
diff --git a/passes/techmap/extract_counter.cc b/passes/techmap/extract_counter.cc
index 56b2ea584..9c814af23 100644
--- a/passes/techmap/extract_counter.cc
+++ b/passes/techmap/extract_counter.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2017 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/extract_fa.cc b/passes/techmap/extract_fa.cc
index 3fcff01c3..117fdd54c 100644
--- a/passes/techmap/extract_fa.cc
+++ b/passes/techmap/extract_fa.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -33,7 +33,7 @@ struct ExtractFaConfig
int maxbreadth = 6;
};
-// http://svn.clifford.at/handicraft/2016/bindec/bindec.c
+// http://svn.clairexen.net/handicraft/2016/bindec/bindec.c
int bindec(unsigned char v)
{
int r = v & 1;
diff --git a/passes/techmap/extract_reduce.cc b/passes/techmap/extract_reduce.cc
index 07b4200cc..892e9a364 100644
--- a/passes/techmap/extract_reduce.cc
+++ b/passes/techmap/extract_reduce.cc
@@ -152,10 +152,10 @@ struct ExtractReducePass : public Pass
log_assert(y.size() == 1);
// Should only continue if there is one fanout back into a cell (not to a port)
- if (sig_to_sink[y[0]].size() != 1)
+ if (sig_to_sink[y].size() != 1 || port_sigs.count(y))
break;
- x = *sig_to_sink[y[0]].begin();
+ x = *sig_to_sink[y].begin();
}
sinks.insert(head_cell);
@@ -183,13 +183,15 @@ struct ExtractReducePass : public Pass
continue;
}
+ auto xy = sigmap(x->getPort(ID::Y));
+
//If this signal drives a port, add it to the sinks
//(even though it may not be the end of a chain)
- if(port_sigs.count(x) && !consumed_cells.count(x))
+ if(port_sigs.count(xy) && !consumed_cells.count(x))
sinks.insert(x);
//It's a match, search everything out from it
- auto& next = sig_to_sink[x];
+ auto& next = sig_to_sink[xy];
for(auto z : next)
next_loads.insert(z);
}
@@ -224,89 +226,60 @@ struct ExtractReducePass : public Pass
if(consumed_cells.count(head_cell))
continue;
- pool<Cell*> cur_supercell;
+ dict<SigBit, int> sources;
+ int inner_cells = 0;
std::deque<Cell*> bfs_queue = {head_cell};
while (bfs_queue.size())
{
Cell* x = bfs_queue.front();
bfs_queue.pop_front();
- cur_supercell.insert(x);
+ for (auto port: {ID::A, ID::B}) {
+ auto bit = sigmap(x->getPort(port)[0]);
- auto a = sigmap(x->getPort(ID::A));
- log_assert(a.size() == 1);
+ bool sink_single = sig_to_sink[bit].size() == 1 && !port_sigs.count(bit);
- // Must have only one sink unless we're going off chain
- // XXX: Check that it is indeed this node?
- if( allow_off_chain || (sig_to_sink[a[0]].size() + port_sigs.count(a[0]) == 1) )
- {
- Cell* cell_a = sig_to_driver[a[0]];
- if(cell_a && IsRightType(cell_a, gt))
- {
- // The cell here is the correct type, and it's definitely driving
- // this current cell.
- bfs_queue.push_back(cell_a);
- }
- }
+ Cell* drv = sig_to_driver[bit];
+ bool drv_ok = drv && drv->type == head_cell->type;
- auto b = sigmap(x->getPort(ID::B));
- log_assert(b.size() == 1);
-
- // Must have only one sink
- // XXX: Check that it is indeed this node?
- if( allow_off_chain || (sig_to_sink[b[0]].size() + port_sigs.count(b[0]) == 1) )
- {
- Cell* cell_b = sig_to_driver[b[0]];
- if(cell_b && IsRightType(cell_b, gt))
- {
- // The cell here is the correct type, and it's definitely driving only
- // this current cell.
- bfs_queue.push_back(cell_b);
+ if (drv_ok && (allow_off_chain || sink_single)) {
+ inner_cells++;
+ bfs_queue.push_back(drv);
+ } else {
+ sources[bit]++;
}
}
}
- log(" Cells:\n");
- for (auto x : cur_supercell)
- log(" %s\n", x->name.c_str());
-
- if (cur_supercell.size() > 1)
+ if (inner_cells)
{
// Worth it to create reduce cell
log(" Creating $reduce_* cell!\n");
- pool<SigBit> input_pool;
- pool<SigBit> input_pool_intermed;
- for (auto x : cur_supercell)
- {
- input_pool.insert(sigmap(x->getPort(ID::A))[0]);
- input_pool.insert(sigmap(x->getPort(ID::B))[0]);
- input_pool_intermed.insert(sigmap(x->getPort(ID::Y))[0]);
- }
- SigSpec input;
- for (auto b : input_pool)
- if (input_pool_intermed.count(b) == 0)
- input.append(b);
-
SigBit output = sigmap(head_cell->getPort(ID::Y)[0]);
- auto new_reduce_cell = module->addCell(NEW_ID,
- gt == GateType::And ? ID($reduce_and) :
- gt == GateType::Or ? ID($reduce_or) :
- gt == GateType::Xor ? ID($reduce_xor) : "");
- new_reduce_cell->setParam(ID::A_SIGNED, 0);
- new_reduce_cell->setParam(ID::A_WIDTH, input.size());
- new_reduce_cell->setParam(ID::Y_WIDTH, 1);
- new_reduce_cell->setPort(ID::A, input);
- new_reduce_cell->setPort(ID::Y, output);
-
- if(allow_off_chain)
- consumed_cells.insert(head_cell);
- else
- {
- for (auto x : cur_supercell)
- consumed_cells.insert(x);
+ SigSpec input;
+ for (auto it : sources) {
+ bool cond;
+ if (head_cell->type == ID($_XOR_))
+ cond = it.second & 1;
+ else
+ cond = it.second != 0;
+ if (cond)
+ input.append(it.first);
+ }
+
+ if (head_cell->type == ID($_AND_)) {
+ module->addReduceAnd(NEW_ID, input, output);
+ } else if (head_cell->type == ID($_OR_)) {
+ module->addReduceOr(NEW_ID, input, output);
+ } else if (head_cell->type == ID($_XOR_)) {
+ module->addReduceXor(NEW_ID, input, output);
+ } else {
+ log_assert(false);
}
+
+ consumed_cells.insert(head_cell);
}
}
}
diff --git a/passes/techmap/extractinv.cc b/passes/techmap/extractinv.cc
index 11463380c..48d9600fa 100644
--- a/passes/techmap/extractinv.cc
+++ b/passes/techmap/extractinv.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2019 Marcelina Kościelnicka <mwk@0x04.net>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/techmap/flatten.cc b/passes/techmap/flatten.cc
index f35b7ff60..7e6df5d2c 100644
--- a/passes/techmap/flatten.cc
+++ b/passes/techmap/flatten.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -77,7 +77,7 @@ struct FlattenWorker
{
bool ignore_wb = false;
- void flatten_cell(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl, std::vector<RTLIL::Cell*> &new_cells)
+ void flatten_cell(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl, SigMap &sigmap, std::vector<RTLIL::Cell*> &new_cells)
{
// Copy the contents of the flattened cell
@@ -122,6 +122,9 @@ struct FlattenWorker
for (auto &tpl_proc_it : tpl->processes) {
RTLIL::Process *new_proc = module->addProcess(map_name(cell, tpl_proc_it.second), tpl_proc_it.second);
map_attributes(cell, new_proc, tpl_proc_it.second->name);
+ for (auto new_proc_sync : new_proc->syncs)
+ for (auto &memwr_action : new_proc_sync->mem_write_actions)
+ memwr_action.memid = memory_map.at(memwr_action.memid).str();
auto rewriter = [&](RTLIL::SigSpec &sig) { map_sigspec(wire_map, sig); };
new_proc->rewrite_sigspecs(rewriter);
design->select(module, new_proc);
@@ -130,10 +133,10 @@ struct FlattenWorker
for (auto tpl_cell : tpl->cells()) {
RTLIL::Cell *new_cell = module->addCell(map_name(cell, tpl_cell), tpl_cell);
map_attributes(cell, new_cell, tpl_cell->name);
- if (new_cell->type.in(ID($memrd), ID($memwr), ID($meminit))) {
+ if (new_cell->has_memid()) {
IdString memid = new_cell->getParam(ID::MEMID).decode_string();
new_cell->setParam(ID::MEMID, Const(memory_map.at(memid).str()));
- } else if (new_cell->type == ID($mem)) {
+ } else if (new_cell->is_mem_cell()) {
IdString memid = new_cell->getParam(ID::MEMID).decode_string();
new_cell->setParam(ID::MEMID, Const(concat_name(cell, memid).str()));
}
@@ -162,7 +165,6 @@ struct FlattenWorker
for (auto bit : tpl_conn.first)
tpl_driven.insert(bit);
- SigMap sigmap(module);
for (auto &port_it : cell->connections())
{
IdString port_name = port_it.first;
@@ -215,6 +217,7 @@ struct FlattenWorker
log_id(module), log_id(cell), log_id(port_it.first), log_signal(new_conn.first), log_signal(new_conn.second));
module->connect(new_conn);
+ sigmap.add(new_conn.first, new_conn.second);
}
module->remove(cell);
@@ -225,6 +228,7 @@ struct FlattenWorker
if (!design->selected(module) || module->get_blackbox_attribute(ignore_wb))
return;
+ SigMap sigmap(module);
std::vector<RTLIL::Cell*> worklist = module->selected_cells();
while (!worklist.empty())
{
@@ -248,7 +252,7 @@ struct FlattenWorker
// If a design is fully selected and has a top module defined, topological sorting ensures that all cells
// added during flattening are black boxes, and flattening is finished in one pass. However, when flattening
// individual modules, this isn't the case, and the newly added cells might have to be flattened further.
- flatten_cell(design, module, cell, tpl, worklist);
+ flatten_cell(design, module, cell, tpl, sigmap, worklist);
}
}
};
diff --git a/passes/techmap/hilomap.cc b/passes/techmap/hilomap.cc
index b808a8d8e..c1b947221 100644
--- a/passes/techmap/hilomap.cc
+++ b/passes/techmap/hilomap.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/insbuf.cc b/passes/techmap/insbuf.cc
index a3b5b698d..68c22c317 100644
--- a/passes/techmap/insbuf.cc
+++ b/passes/techmap/insbuf.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc
index e8530a034..437ad5156 100644
--- a/passes/techmap/iopadmap.cc
+++ b/passes/techmap/iopadmap.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -43,26 +43,28 @@ struct IopadmapPass : public Pass {
log("can only map to very simple PAD cells. Use 'techmap' to further map\n");
log("the resulting cells to more sophisticated PAD cells.\n");
log("\n");
- log(" -inpad <celltype> <portname>[:<portname>]\n");
+ log(" -inpad <celltype> <in_port>[:<ext_port>]\n");
log(" Map module input ports to the given cell type with the\n");
log(" given output port name. if a 2nd portname is given, the\n");
- log(" signal is passed through the pad call, using the 2nd\n");
+ log(" signal is passed through the pad cell, using the 2nd\n");
log(" portname as the port facing the module port.\n");
log("\n");
- log(" -outpad <celltype> <portname>[:<portname>]\n");
- log(" -inoutpad <celltype> <portname>[:<portname>]\n");
+ log(" -outpad <celltype> <out_port>[:<ext_port>]\n");
+ log(" -inoutpad <celltype> <io_port>[:<ext_port>]\n");
log(" Similar to -inpad, but for output and inout ports.\n");
log("\n");
- log(" -toutpad <celltype> <portname>:<portname>[:<portname>]\n");
+ log(" -toutpad <celltype> <oe_port>:<out_port>[:<ext_port>]\n");
log(" Merges $_TBUF_ cells into the output pad cell. This takes precedence\n");
log(" over the other -outpad cell. The first portname is the enable input\n");
- log(" of the tristate driver.\n");
+ log(" of the tristate driver, which can be prefixed with `~` for negative\n");
+ log(" polarity enable.\n");
log("\n");
- log(" -tinoutpad <celltype> <portname>:<portname>:<portname>[:<portname>]\n");
+ log(" -tinoutpad <celltype> <oe_port>:<in_port>:<out_port>[:<ext_port>]\n");
log(" Merges $_TBUF_ cells into the inout pad cell. This takes precedence\n");
log(" over the other -inoutpad cell. The first portname is the enable input\n");
log(" of the tristate driver and the 2nd portname is the internal output\n");
- log(" buffering the external signal.\n");
+ log(" buffering the external signal. Like with `-toutpad`, the enable can\n");
+ log(" be marked as negative polarity by prefixing the name with `~`.\n");
log("\n");
log(" -ignore <celltype> <portname>[:<portname>]*\n");
log(" Skips mapping inputs/outputs that are already connected to given\n");
@@ -106,6 +108,7 @@ struct IopadmapPass : public Pass {
std::string inoutpad_celltype, inoutpad_portname_io, inoutpad_portname_pad;
std::string toutpad_celltype, toutpad_portname_oe, toutpad_portname_i, toutpad_portname_pad;
std::string tinoutpad_celltype, tinoutpad_portname_oe, tinoutpad_portname_o, tinoutpad_portname_i, tinoutpad_portname_pad;
+ bool toutpad_neg_oe = false, tinoutpad_neg_oe = false;
std::string widthparam, nameparam;
pool<pair<IdString, IdString>> ignore;
bool flag_bits = false;
@@ -137,6 +140,10 @@ struct IopadmapPass : public Pass {
toutpad_portname_oe = args[++argidx];
split_portname_pair(toutpad_portname_oe, toutpad_portname_i);
split_portname_pair(toutpad_portname_i, toutpad_portname_pad);
+ if (toutpad_portname_oe[0] == '~') {
+ toutpad_neg_oe = true;
+ toutpad_portname_oe = toutpad_portname_oe.substr(1);
+ }
continue;
}
if (arg == "-tinoutpad" && argidx+2 < args.size()) {
@@ -145,6 +152,10 @@ struct IopadmapPass : public Pass {
split_portname_pair(tinoutpad_portname_oe, tinoutpad_portname_o);
split_portname_pair(tinoutpad_portname_o, tinoutpad_portname_i);
split_portname_pair(tinoutpad_portname_i, tinoutpad_portname_pad);
+ if (tinoutpad_portname_oe[0] == '~') {
+ tinoutpad_neg_oe = true;
+ tinoutpad_portname_oe = tinoutpad_portname_oe.substr(1);
+ }
continue;
}
if (arg == "-ignore" && argidx+2 < args.size()) {
@@ -318,6 +329,8 @@ struct IopadmapPass : public Pass {
module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)),
RTLIL::escape_id(tinoutpad_celltype));
+ if (tinoutpad_neg_oe)
+ en_sig = module->NotGate(NEW_ID, en_sig);
cell->setPort(RTLIL::escape_id(tinoutpad_portname_oe), en_sig);
cell->attributes[ID::keep] = RTLIL::Const(1);
@@ -340,6 +353,8 @@ struct IopadmapPass : public Pass {
module->uniquify(stringf("$iopadmap$%s.%s[%d]", log_id(module), log_id(wire), i)),
RTLIL::escape_id(toutpad_celltype));
+ if (toutpad_neg_oe)
+ en_sig = module->NotGate(NEW_ID, en_sig);
cell->setPort(RTLIL::escape_id(toutpad_portname_oe), en_sig);
cell->setPort(RTLIL::escape_id(toutpad_portname_i), data_sig);
cell->attributes[ID::keep] = RTLIL::Const(1);
diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc
index 349ccc115..3d0ebaea3 100644
--- a/passes/techmap/libparse.cc
+++ b/passes/techmap/libparse.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -384,7 +384,7 @@ void LibertyParser::error(const std::string &str)
exit(1);
}
-/**** BEGIN: http://svn.clifford.at/tools/trunk/examples/check.h ****/
+/**** BEGIN: http://svn.clairexen.net/tools/trunk/examples/check.h ****/
#define CHECK_NV(result, check) \
do { \
@@ -405,7 +405,7 @@ void LibertyParser::error(const std::string &str)
} \
} while(0)
-/**** END: http://svn.clifford.at/tools/trunk/examples/check.h ****/
+/**** END: http://svn.clairexen.net/tools/trunk/examples/check.h ****/
LibertyAst *find_non_null(LibertyAst *node, const char *name)
{
diff --git a/passes/techmap/libparse.h b/passes/techmap/libparse.h
index c9ebd06c5..77e305f0b 100644
--- a/passes/techmap/libparse.h
+++ b/passes/techmap/libparse.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/lut2mux.cc b/passes/techmap/lut2mux.cc
index f56eff3e5..ef76e0deb 100644
--- a/passes/techmap/lut2mux.cc
+++ b/passes/techmap/lut2mux.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/maccmap.cc b/passes/techmap/maccmap.cc
index 43f2d97f5..2235bdef9 100644
--- a/passes/techmap/maccmap.cc
+++ b/passes/techmap/maccmap.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/muxcover.cc b/passes/techmap/muxcover.cc
index 24109b579..a90d81985 100644
--- a/passes/techmap/muxcover.cc
+++ b/passes/techmap/muxcover.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/nlutmap.cc b/passes/techmap/nlutmap.cc
index e1ebfcad8..016789157 100644
--- a/passes/techmap/nlutmap.cc
+++ b/passes/techmap/nlutmap.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/pmuxtree.cc b/passes/techmap/pmuxtree.cc
index b937d3fb0..ff6bb549b 100644
--- a/passes/techmap/pmuxtree.cc
+++ b/passes/techmap/pmuxtree.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc
index b971068f7..928182970 100644
--- a/passes/techmap/shregmap.cc
+++ b/passes/techmap/shregmap.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc
index b9d337da4..7d8dba439 100644
--- a/passes/techmap/simplemap.cc
+++ b/passes/techmap/simplemap.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -19,6 +19,7 @@
#include "simplemap.h"
#include "kernel/sigtools.h"
+#include "kernel/ff.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -298,6 +299,30 @@ void simplemap_tribuf(RTLIL::Module *module, RTLIL::Cell *cell)
}
}
+void simplemap_bmux(RTLIL::Module *module, RTLIL::Cell *cell)
+{
+ SigSpec sel = cell->getPort(ID::S);
+ SigSpec data = cell->getPort(ID::A);
+ int width = GetSize(cell->getPort(ID::Y));
+
+ for (int idx = 0; idx < GetSize(sel); idx++) {
+ SigSpec new_data = module->addWire(NEW_ID, GetSize(data)/2);
+ for (int i = 0; i < GetSize(new_data); i += width) {
+ for (int k = 0; k < width; k++) {
+ RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
+ gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ gate->setPort(ID::A, data[i*2+k]);
+ gate->setPort(ID::B, data[i*2+width+k]);
+ gate->setPort(ID::S, sel[idx]);
+ gate->setPort(ID::Y, new_data[i+k]);
+ }
+ }
+ data = new_data;
+ }
+
+ module->connect(cell->getPort(ID::Y), data);
+}
+
void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell)
{
SigSpec lut_ctrl = cell->getPort(ID::A);
@@ -305,7 +330,6 @@ void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell)
lut_data.extend_u0(1 << cell->getParam(ID::WIDTH).as_int());
for (int idx = 0; GetSize(lut_data) > 1; idx++) {
- SigSpec sig_s = lut_ctrl[idx];
SigSpec new_lut_data = module->addWire(NEW_ID, GetSize(lut_data)/2);
for (int i = 0; i < GetSize(lut_data); i += 2) {
RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
@@ -367,276 +391,13 @@ void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell)
module->connect(RTLIL::SigSig(sig_y, sig_ab));
}
-void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell)
-{
- int width = cell->parameters.at(ID::WIDTH).as_int();
- char set_pol = cell->parameters.at(ID::SET_POLARITY).as_bool() ? 'P' : 'N';
- char clr_pol = cell->parameters.at(ID::CLR_POLARITY).as_bool() ? 'P' : 'N';
-
- RTLIL::SigSpec sig_s = cell->getPort(ID::SET);
- RTLIL::SigSpec sig_r = cell->getPort(ID::CLR);
- RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
-
- std::string gate_type = stringf("$_SR_%c%c_", set_pol, clr_pol);
-
- for (int i = 0; i < width; i++) {
- RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
- gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
- gate->setPort(ID::S, sig_s[i]);
- gate->setPort(ID::R, sig_r[i]);
- gate->setPort(ID::Q, sig_q[i]);
- }
-}
-
-void simplemap_ff(RTLIL::Module *module, RTLIL::Cell *cell)
-{
- int width = cell->parameters.at(ID::WIDTH).as_int();
-
- RTLIL::SigSpec sig_d = cell->getPort(ID::D);
- RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
-
- IdString gate_type = ID($_FF_);
-
- for (int i = 0; i < width; i++) {
- RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
- gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
- gate->setPort(ID::D, sig_d[i]);
- gate->setPort(ID::Q, sig_q[i]);
- }
-}
-
-void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_ff(RTLIL::Module *, RTLIL::Cell *cell)
{
- int width = cell->parameters.at(ID::WIDTH).as_int();
- char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N';
-
- RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK);
- RTLIL::SigSpec sig_d = cell->getPort(ID::D);
- RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
-
- IdString gate_type = stringf("$_DFF_%c_", clk_pol);
-
- for (int i = 0; i < width; i++) {
- RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
- gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
- gate->setPort(ID::C, sig_clk);
- gate->setPort(ID::D, sig_d[i]);
- gate->setPort(ID::Q, sig_q[i]);
- }
-}
-
-void simplemap_dffe(RTLIL::Module *module, RTLIL::Cell *cell)
-{
- int width = cell->parameters.at(ID::WIDTH).as_int();
- char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N';
- char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N';
-
- RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK);
- RTLIL::SigSpec sig_en = cell->getPort(ID::EN);
- RTLIL::SigSpec sig_d = cell->getPort(ID::D);
- RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
-
- IdString gate_type = stringf("$_DFFE_%c%c_", clk_pol, en_pol);
-
- for (int i = 0; i < width; i++) {
- RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
- gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
- gate->setPort(ID::C, sig_clk);
- gate->setPort(ID::E, sig_en);
- gate->setPort(ID::D, sig_d[i]);
- gate->setPort(ID::Q, sig_q[i]);
- }
-}
-
-void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell)
-{
- int width = cell->parameters.at(ID::WIDTH).as_int();
- char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N';
- char set_pol = cell->parameters.at(ID::SET_POLARITY).as_bool() ? 'P' : 'N';
- char clr_pol = cell->parameters.at(ID::CLR_POLARITY).as_bool() ? 'P' : 'N';
-
- RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK);
- RTLIL::SigSpec sig_s = cell->getPort(ID::SET);
- RTLIL::SigSpec sig_r = cell->getPort(ID::CLR);
- RTLIL::SigSpec sig_d = cell->getPort(ID::D);
- RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
-
- IdString gate_type = stringf("$_DFFSR_%c%c%c_", clk_pol, set_pol, clr_pol);
-
- for (int i = 0; i < width; i++) {
- RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
- gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
- gate->setPort(ID::C, sig_clk);
- gate->setPort(ID::S, sig_s[i]);
- gate->setPort(ID::R, sig_r[i]);
- gate->setPort(ID::D, sig_d[i]);
- gate->setPort(ID::Q, sig_q[i]);
- }
-}
-
-void simplemap_dffsre(RTLIL::Module *module, RTLIL::Cell *cell)
-{
- int width = cell->parameters.at(ID::WIDTH).as_int();
- char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N';
- char set_pol = cell->parameters.at(ID::SET_POLARITY).as_bool() ? 'P' : 'N';
- char clr_pol = cell->parameters.at(ID::CLR_POLARITY).as_bool() ? 'P' : 'N';
- char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N';
-
- RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK);
- RTLIL::SigSpec sig_s = cell->getPort(ID::SET);
- RTLIL::SigSpec sig_r = cell->getPort(ID::CLR);
- RTLIL::SigSpec sig_e = cell->getPort(ID::EN);
- RTLIL::SigSpec sig_d = cell->getPort(ID::D);
- RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
-
- IdString gate_type = stringf("$_DFFSRE_%c%c%c%c_", clk_pol, set_pol, clr_pol, en_pol);
-
- for (int i = 0; i < width; i++) {
- RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
- gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
- gate->setPort(ID::C, sig_clk);
- gate->setPort(ID::S, sig_s[i]);
- gate->setPort(ID::R, sig_r[i]);
- gate->setPort(ID::E, sig_e);
- gate->setPort(ID::D, sig_d[i]);
- gate->setPort(ID::Q, sig_q[i]);
- }
-}
-
-void simplemap_adff_sdff(RTLIL::Module *module, RTLIL::Cell *cell)
-{
- int width = cell->parameters.at(ID::WIDTH).as_int();
- bool is_async = cell->type == ID($adff);
- char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N';
- char rst_pol = cell->parameters.at(is_async ? ID::ARST_POLARITY : ID::SRST_POLARITY).as_bool() ? 'P' : 'N';
- const char *type = is_async ? "DFF" : "SDFF";
-
- std::vector<RTLIL::State> rst_val = cell->parameters.at(is_async ? ID::ARST_VALUE : ID::SRST_VALUE).bits;
- while (int(rst_val.size()) < width)
- rst_val.push_back(RTLIL::State::S0);
-
- RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK);
- RTLIL::SigSpec sig_rst = cell->getPort(is_async ? ID::ARST : ID::SRST);
- RTLIL::SigSpec sig_d = cell->getPort(ID::D);
- RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
-
- IdString gate_type_0 = stringf("$_%s_%c%c0_", type, clk_pol, rst_pol);
- IdString gate_type_1 = stringf("$_%s_%c%c1_", type, clk_pol, rst_pol);
-
- for (int i = 0; i < width; i++) {
- RTLIL::Cell *gate = module->addCell(NEW_ID, rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0);
- gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
- gate->setPort(ID::C, sig_clk);
- gate->setPort(ID::R, sig_rst);
- gate->setPort(ID::D, sig_d[i]);
- gate->setPort(ID::Q, sig_q[i]);
- }
-}
-
-void simplemap_adffe_sdffe_sdffce(RTLIL::Module *module, RTLIL::Cell *cell)
-{
- int width = cell->parameters.at(ID::WIDTH).as_int();
- bool is_async = cell->type == ID($adffe);
- char clk_pol = cell->parameters.at(ID::CLK_POLARITY).as_bool() ? 'P' : 'N';
- char rst_pol = cell->parameters.at(is_async ? ID::ARST_POLARITY : ID::SRST_POLARITY).as_bool() ? 'P' : 'N';
- char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N';
- const char *type = is_async ? "DFFE" : cell->type == ID($sdffe) ? "SDFFE" : "SDFFCE";
-
- std::vector<RTLIL::State> rst_val = cell->parameters.at(is_async ? ID::ARST_VALUE : ID::SRST_VALUE).bits;
- while (int(rst_val.size()) < width)
- rst_val.push_back(RTLIL::State::S0);
-
- RTLIL::SigSpec sig_clk = cell->getPort(ID::CLK);
- RTLIL::SigSpec sig_rst = cell->getPort(is_async ? ID::ARST : ID::SRST);
- RTLIL::SigSpec sig_e = cell->getPort(ID::EN);
- RTLIL::SigSpec sig_d = cell->getPort(ID::D);
- RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
-
- IdString gate_type_0 = stringf("$_%s_%c%c0%c_", type, clk_pol, rst_pol, en_pol);
- IdString gate_type_1 = stringf("$_%s_%c%c1%c_", type, clk_pol, rst_pol, en_pol);
-
- for (int i = 0; i < width; i++) {
- RTLIL::Cell *gate = module->addCell(NEW_ID, rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0);
- gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
- gate->setPort(ID::C, sig_clk);
- gate->setPort(ID::R, sig_rst);
- gate->setPort(ID::E, sig_e);
- gate->setPort(ID::D, sig_d[i]);
- gate->setPort(ID::Q, sig_q[i]);
- }
-}
-
-void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell)
-{
- int width = cell->parameters.at(ID::WIDTH).as_int();
- char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N';
-
- RTLIL::SigSpec sig_en = cell->getPort(ID::EN);
- RTLIL::SigSpec sig_d = cell->getPort(ID::D);
- RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
-
- IdString gate_type = stringf("$_DLATCH_%c_", en_pol);
-
- for (int i = 0; i < width; i++) {
- RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
- gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
- gate->setPort(ID::E, sig_en);
- gate->setPort(ID::D, sig_d[i]);
- gate->setPort(ID::Q, sig_q[i]);
- }
-}
-
-void simplemap_adlatch(RTLIL::Module *module, RTLIL::Cell *cell)
-{
- int width = cell->parameters.at(ID::WIDTH).as_int();
- char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N';
- char rst_pol = cell->parameters.at(ID::ARST_POLARITY).as_bool() ? 'P' : 'N';
-
- std::vector<RTLIL::State> rst_val = cell->parameters.at(ID::ARST_VALUE).bits;
- while (int(rst_val.size()) < width)
- rst_val.push_back(RTLIL::State::S0);
-
- RTLIL::SigSpec sig_en = cell->getPort(ID::EN);
- RTLIL::SigSpec sig_rst = cell->getPort(ID::ARST);
- RTLIL::SigSpec sig_d = cell->getPort(ID::D);
- RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
-
- IdString gate_type_0 = stringf("$_DLATCH_%c%c0_", en_pol, rst_pol);
- IdString gate_type_1 = stringf("$_DLATCH_%c%c1_", en_pol, rst_pol);
-
- for (int i = 0; i < width; i++) {
- RTLIL::Cell *gate = module->addCell(NEW_ID, rst_val.at(i) == RTLIL::State::S1 ? gate_type_1 : gate_type_0);
- gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
- gate->setPort(ID::E, sig_en);
- gate->setPort(ID::R, sig_rst);
- gate->setPort(ID::D, sig_d[i]);
- gate->setPort(ID::Q, sig_q[i]);
- }
-}
-
-void simplemap_dlatchsr(RTLIL::Module *module, RTLIL::Cell *cell)
-{
- int width = cell->parameters.at(ID::WIDTH).as_int();
- char en_pol = cell->parameters.at(ID::EN_POLARITY).as_bool() ? 'P' : 'N';
- char set_pol = cell->parameters.at(ID::SET_POLARITY).as_bool() ? 'P' : 'N';
- char clr_pol = cell->parameters.at(ID::CLR_POLARITY).as_bool() ? 'P' : 'N';
-
- RTLIL::SigSpec sig_en = cell->getPort(ID::EN);
- RTLIL::SigSpec sig_s = cell->getPort(ID::SET);
- RTLIL::SigSpec sig_r = cell->getPort(ID::CLR);
- RTLIL::SigSpec sig_d = cell->getPort(ID::D);
- RTLIL::SigSpec sig_q = cell->getPort(ID::Q);
-
- IdString gate_type = stringf("$_DLATCHSR_%c%c%c_", en_pol, set_pol, clr_pol);
-
- for (int i = 0; i < width; i++) {
- RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
- gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
- gate->setPort(ID::E, sig_en);
- gate->setPort(ID::S, sig_s[i]);
- gate->setPort(ID::R, sig_r[i]);
- gate->setPort(ID::D, sig_d[i]);
- gate->setPort(ID::Q, sig_q[i]);
+ FfData ff(nullptr, cell);
+ for (int i = 0; i < ff.width; i++) {
+ FfData fff = ff.slice({i});
+ fff.is_fine = true;
+ fff.emit();
}
}
@@ -662,24 +423,27 @@ void simplemap_get_mappers(dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)>
mappers[ID($nex)] = simplemap_eqne;
mappers[ID($mux)] = simplemap_mux;
mappers[ID($tribuf)] = simplemap_tribuf;
+ mappers[ID($bmux)] = simplemap_bmux;
mappers[ID($lut)] = simplemap_lut;
mappers[ID($sop)] = simplemap_sop;
mappers[ID($slice)] = simplemap_slice;
mappers[ID($concat)] = simplemap_concat;
- mappers[ID($sr)] = simplemap_sr;
+ mappers[ID($sr)] = simplemap_ff;
mappers[ID($ff)] = simplemap_ff;
- mappers[ID($dff)] = simplemap_dff;
- mappers[ID($dffe)] = simplemap_dffe;
- mappers[ID($dffsr)] = simplemap_dffsr;
- mappers[ID($dffsre)] = simplemap_dffsre;
- mappers[ID($adff)] = simplemap_adff_sdff;
- mappers[ID($sdff)] = simplemap_adff_sdff;
- mappers[ID($adffe)] = simplemap_adffe_sdffe_sdffce;
- mappers[ID($sdffe)] = simplemap_adffe_sdffe_sdffce;
- mappers[ID($sdffce)] = simplemap_adffe_sdffe_sdffce;
- mappers[ID($dlatch)] = simplemap_dlatch;
- mappers[ID($adlatch)] = simplemap_adlatch;
- mappers[ID($dlatchsr)] = simplemap_dlatchsr;
+ mappers[ID($dff)] = simplemap_ff;
+ mappers[ID($dffe)] = simplemap_ff;
+ mappers[ID($dffsr)] = simplemap_ff;
+ mappers[ID($dffsre)] = simplemap_ff;
+ mappers[ID($adff)] = simplemap_ff;
+ mappers[ID($sdff)] = simplemap_ff;
+ mappers[ID($adffe)] = simplemap_ff;
+ mappers[ID($sdffe)] = simplemap_ff;
+ mappers[ID($sdffce)] = simplemap_ff;
+ mappers[ID($aldff)] = simplemap_ff;
+ mappers[ID($aldffe)] = simplemap_ff;
+ mappers[ID($dlatch)] = simplemap_ff;
+ mappers[ID($adlatch)] = simplemap_ff;
+ mappers[ID($dlatchsr)] = simplemap_ff;
}
void simplemap(RTLIL::Module *module, RTLIL::Cell *cell)
@@ -712,7 +476,7 @@ struct SimplemapPass : public Pass {
log(" $not, $pos, $and, $or, $xor, $xnor\n");
log(" $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n");
log(" $logic_not, $logic_and, $logic_or, $mux, $tribuf\n");
- log(" $sr, $ff, $dff, $dffe, $dffsr, $dffsre, $adff, $adffe, $sdff, $sdffe, $sdffce, $dlatch, $adlatch, $dlatchsr\n");
+ log(" $sr, $ff, $dff, $dffe, $dffsr, $dffsre, $adff, $adffe, $aldff, $aldffe, $sdff, $sdffe, $sdffce, $dlatch, $adlatch, $dlatchsr\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
diff --git a/passes/techmap/simplemap.h b/passes/techmap/simplemap.h
index 5091050a1..c7654f68c 100644
--- a/passes/techmap/simplemap.h
+++ b/passes/techmap/simplemap.h
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -34,12 +34,7 @@ extern void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell);
extern void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell);
extern void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell);
extern void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell);
-extern void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell);
-extern void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell);
-extern void simplemap_dffe(RTLIL::Module *module, RTLIL::Cell *cell);
-extern void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell);
-extern void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell);
-extern void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell);
+extern void simplemap_ff(RTLIL::Module *module, RTLIL::Cell *cell);
extern void simplemap(RTLIL::Module *module, RTLIL::Cell *cell);
extern void simplemap_get_mappers(dict<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers);
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index 96843d710..5cd78fe28 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -364,13 +364,11 @@ struct TechmapWorker
for (auto &it2 : autopurge_ports)
c->unsetPort(it2);
- if (c->type.in(ID($memrd), ID($memwr), ID($meminit))) {
+ if (c->has_memid()) {
IdString memid = c->getParam(ID::MEMID).decode_string();
log_assert(memory_renames.count(memid) != 0);
c->setParam(ID::MEMID, Const(memory_renames[memid].str()));
- }
-
- if (c->type == ID($mem)) {
+ } else if (c->is_mem_cell()) {
IdString memid = c->getParam(ID::MEMID).decode_string();
apply_prefix(cell->name, memid);
c->setParam(ID::MEMID, Const(memid.c_str()));
@@ -379,10 +377,12 @@ struct TechmapWorker
if (c->attributes.count(ID::src))
c->add_strpool_attribute(ID::src, extra_src_attrs);
- if (techmap_replace_cell)
+ if (techmap_replace_cell) {
for (auto attr : cell->attributes)
if (!c->attributes.count(attr.first))
c->attributes[attr.first] = attr.second;
+ c->attributes.erase(ID::reprocess_after);
+ }
}
for (auto &it : tpl->connections()) {
diff --git a/passes/techmap/tribuf.cc b/passes/techmap/tribuf.cc
index 79ddb4bd7..f92b4cdb0 100644
--- a/passes/techmap/tribuf.cc
+++ b/passes/techmap/tribuf.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc
index e3b4ae573..cc208c516 100644
--- a/passes/techmap/zinit.cc
+++ b/passes/techmap/zinit.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -20,6 +20,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include "kernel/ffinit.h"
+#include "kernel/ff.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -60,123 +61,25 @@ struct ZinitPass : public Pass {
SigMap sigmap(module);
FfInitVals initvals(&sigmap, module);
- pool<IdString> dff_types = {
- // FIXME: It would appear that supporting
- // $dffsr/$_DFFSR_* would require a new
- // cell type where S has priority over R
- ID($ff), ID($dff), ID($dffe), /*ID($dffsr),*/ ID($adff), ID($adffe),
- ID($sdff), ID($sdffe), ID($sdffce),
- ID($_FF_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
- /*ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
- ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),*/
- ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
- ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
- // Async set/reset
- ID($_DFFE_NN0P_), ID($_DFFE_NN1P_), ID($_DFFE_NP0P_), ID($_DFFE_NP1P_),
- ID($_DFFE_PN0P_), ID($_DFFE_PN1P_), ID($_DFFE_PP0P_), ID($_DFFE_PP1P_),
- ID($_DFFE_NN0N_), ID($_DFFE_NN1N_), ID($_DFFE_NP0N_), ID($_DFFE_NP1N_),
- ID($_DFFE_PN0N_), ID($_DFFE_PN1N_), ID($_DFFE_PP0N_), ID($_DFFE_PP1N_),
- // Sync set/reset
- ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), ID($_SDFF_NP1_),
- ID($_SDFF_PN0_), ID($_SDFF_PN1_), ID($_SDFF_PP0_), ID($_SDFF_PP1_),
- ID($_SDFFE_NN0P_), ID($_SDFFE_NN1P_), ID($_SDFFE_NP0P_), ID($_SDFFE_NP1P_),
- ID($_SDFFE_PN0P_), ID($_SDFFE_PN1P_), ID($_SDFFE_PP0P_), ID($_SDFFE_PP1P_),
- ID($_SDFFE_NN0N_), ID($_SDFFE_NN1N_), ID($_SDFFE_NP0N_), ID($_SDFFE_NP1N_),
- ID($_SDFFE_PN0N_), ID($_SDFFE_PN1N_), ID($_SDFFE_PP0N_), ID($_SDFFE_PP1N_),
- ID($_SDFFCE_NN0P_), ID($_SDFFCE_NN1P_), ID($_SDFFCE_NP0P_), ID($_SDFFCE_NP1P_),
- ID($_SDFFCE_PN0P_), ID($_SDFFCE_PN1P_), ID($_SDFFCE_PP0P_), ID($_SDFFCE_PP1P_),
- ID($_SDFFCE_NN0N_), ID($_SDFFCE_NN1N_), ID($_SDFFCE_NP0N_), ID($_SDFFCE_NP1N_),
- ID($_SDFFCE_PN0N_), ID($_SDFFCE_PN1N_), ID($_SDFFCE_PP0N_), ID($_SDFFCE_PP1N_)
- };
-
for (auto cell : module->selected_cells())
{
- if (!dff_types.count(cell->type))
- continue;
-
- SigSpec sig_d = sigmap(cell->getPort(ID::D));
- SigSpec sig_q = sigmap(cell->getPort(ID::Q));
-
- if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
+ if (!RTLIL::builtin_ff_cell_types().count(cell->type))
continue;
- Const initval = initvals(sig_q);
- Const newval = initval;
- initvals.remove_init(sig_q);
-
- Wire *initwire = module->addWire(NEW_ID, GetSize(sig_q));
-
- for (int i = 0; i < GetSize(initwire); i++)
- if (initval[i] == State::S1)
- {
- sig_d[i] = module->NotGate(NEW_ID, sig_d[i]);
- module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[i]);
- newval[i] = State::S0;
- }
- else
- {
- module->connect(sig_q[i], SigSpec(initwire, i));
- if (all_mode)
- newval[i] = State::S0;
- }
-
- initvals.set_init(initwire, newval);
+ FfData ff(&initvals, cell);
log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type),
- log_signal(sig_q), log_signal(initval));
-
- cell->setPort(ID::D, sig_d);
- cell->setPort(ID::Q, initwire);
-
- if (cell->type.in(ID($adff), ID($adffe))) {
- auto val = cell->getParam(ID::ARST_VALUE);
- for (int i = 0; i < GetSize(initwire); i++)
- if (initval[i] == State::S1)
- val[i] = (val[i] == State::S1 ? State::S0 : State::S1);
- cell->setParam(ID::ARST_VALUE, std::move(val));
- }
- else if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce))) {
- auto val = cell->getParam(ID::SRST_VALUE);
- for (int i = 0; i < GetSize(initwire); i++)
- if (initval[i] == State::S1)
- val[i] = (val[i] == State::S1 ? State::S0 : State::S1);
- cell->setParam(ID::SRST_VALUE, std::move(val));
- }
- else if (initval == State::S1) {
- std::string t = cell->type.str();
- if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
- ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)))
- {
- t[8] = (t[8] == '0' ? '1' : '0');
- }
- else if (cell->type.in(ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), ID($_SDFF_NP1_),
- ID($_SDFF_PN0_), ID($_SDFF_PN1_), ID($_SDFF_PP0_), ID($_SDFF_PP1_)))
- {
- t[9] = (t[9] == '0' ? '1' : '0');
- }
- else if (cell->type.in(ID($_DFFE_NN0P_), ID($_DFFE_NN1P_), ID($_DFFE_NP0P_), ID($_DFFE_NP1P_),
- ID($_DFFE_PN0P_), ID($_DFFE_PN1P_), ID($_DFFE_PP0P_), ID($_DFFE_PP1P_),
- ID($_DFFE_NN0N_), ID($_DFFE_NN1N_), ID($_DFFE_NP0N_), ID($_DFFE_NP1N_),
- ID($_DFFE_PN0N_), ID($_DFFE_PN1N_), ID($_DFFE_PP0N_), ID($_DFFE_PP1N_)))
- {
- t[9] = (t[9] == '0' ? '1' : '0');
- }
- else if (cell->type.in(ID($_SDFFE_NN0P_), ID($_SDFFE_NN1P_), ID($_SDFFE_NP0P_), ID($_SDFFE_NP1P_),
- ID($_SDFFE_PN0P_), ID($_SDFFE_PN1P_), ID($_SDFFE_PP0P_), ID($_SDFFE_PP1P_),
- ID($_SDFFE_NN0N_), ID($_SDFFE_NN1N_), ID($_SDFFE_NP0N_), ID($_SDFFE_NP1N_),
- ID($_SDFFE_PN0N_), ID($_SDFFE_PN1N_), ID($_SDFFE_PP0N_), ID($_SDFFE_PP1N_)))
- {
- t[10] = (t[10] == '0' ? '1' : '0');
- }
- else if (cell->type.in(ID($_SDFFCE_NN0P_), ID($_SDFFCE_NN1P_), ID($_SDFFCE_NP0P_), ID($_SDFFCE_NP1P_),
- ID($_SDFFCE_PN0P_), ID($_SDFFCE_PN1P_), ID($_SDFFCE_PP0P_), ID($_SDFFCE_PP1P_),
- ID($_SDFFCE_NN0N_), ID($_SDFFCE_NN1N_), ID($_SDFFCE_NP0N_), ID($_SDFFCE_NP1N_),
- ID($_SDFFCE_PN0N_), ID($_SDFFCE_PN1N_), ID($_SDFFCE_PP0N_), ID($_SDFFCE_PP1N_)))
- {
- t[11] = (t[11] == '0' ? '1' : '0');
- }
- cell->type = t;
+ log_signal(ff.sig_q), log_signal(ff.val_init));
+
+ pool<int> bits;
+ for (int i = 0; i < ff.width; i++) {
+ if (ff.val_init.bits[i] == State::S1)
+ bits.insert(i);
+ else if (ff.val_init.bits[i] != State::S0 && all_mode)
+ ff.val_init.bits[i] = State::S0;
}
+ ff.flip_bits(bits);
+ ff.emit();
}
}
}
diff --git a/passes/tests/test_abcloop.cc b/passes/tests/test_abcloop.cc
index ac31e36f1..9e7adaab1 100644
--- a/passes/tests/test_abcloop.cc
+++ b/passes/tests/test_abcloop.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/passes/tests/test_autotb.cc b/passes/tests/test_autotb.cc
index 4ab46014d..404d1e48d 100644
--- a/passes/tests/test_autotb.cc
+++ b/passes/tests/test_autotb.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc
index 616981f32..e21ec452c 100644
--- a/passes/tests/test_cell.cc
+++ b/passes/tests/test_cell.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2014 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -69,6 +69,48 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type,
cell->setPort(ID::Y, wire);
}
+ if (cell_type == ID($bmux))
+ {
+ int width = 1 + xorshift32(8);
+ int swidth = 1 + xorshift32(4);
+
+ wire = module->addWire(ID::A);
+ wire->width = width << swidth;
+ wire->port_input = true;
+ cell->setPort(ID::A, wire);
+
+ wire = module->addWire(ID::S);
+ wire->width = swidth;
+ wire->port_input = true;
+ cell->setPort(ID::S, wire);
+
+ wire = module->addWire(ID::Y);
+ wire->width = width;
+ wire->port_output = true;
+ cell->setPort(ID::Y, wire);
+ }
+
+ if (cell_type == ID($demux))
+ {
+ int width = 1 + xorshift32(8);
+ int swidth = 1 + xorshift32(6);
+
+ wire = module->addWire(ID::A);
+ wire->width = width;
+ wire->port_input = true;
+ cell->setPort(ID::A, wire);
+
+ wire = module->addWire(ID::S);
+ wire->width = swidth;
+ wire->port_input = true;
+ cell->setPort(ID::S, wire);
+
+ wire = module->addWire(ID::Y);
+ wire->width = width << swidth;
+ wire->port_output = true;
+ cell->setPort(ID::Y, wire);
+ }
+
if (cell_type == ID($fa))
{
int width = 1 + xorshift32(8);
@@ -855,8 +897,10 @@ struct TestCellPass : public Pass {
cell_types[ID($logic_and)] = "ABSY";
cell_types[ID($logic_or)] = "ABSY";
+ cell_types[ID($mux)] = "*";
+ cell_types[ID($bmux)] = "*";
+ cell_types[ID($demux)] = "*";
if (edges) {
- cell_types[ID($mux)] = "*";
cell_types[ID($pmux)] = "*";
}
diff --git a/techlibs/achronix/speedster22i/cells_arith.v b/techlibs/achronix/speedster22i/cells_arith.v
index 8529706a7..ac78ff660 100644
--- a/techlibs/achronix/speedster22i/cells_arith.v
+++ b/techlibs/achronix/speedster22i/cells_arith.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/achronix/speedster22i/cells_map.v b/techlibs/achronix/speedster22i/cells_map.v
index a19e53f49..04288baa7 100644
--- a/techlibs/achronix/speedster22i/cells_map.v
+++ b/techlibs/achronix/speedster22i/cells_map.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/achronix/speedster22i/cells_sim.v b/techlibs/achronix/speedster22i/cells_sim.v
index a0c60b4be..6c87adb94 100644
--- a/techlibs/achronix/speedster22i/cells_sim.v
+++ b/techlibs/achronix/speedster22i/cells_sim.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/achronix/synth_achronix.cc b/techlibs/achronix/synth_achronix.cc
index b203828d2..9a0a7a3b5 100644
--- a/techlibs/achronix/synth_achronix.cc
+++ b/techlibs/achronix/synth_achronix.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -173,6 +173,7 @@ struct SynthAchronixPass : public ScriptPass {
run("hierarchy -check");
run("stat");
run("check -noinit");
+ run("blackbox =A:whitebox");
}
if (check_label("vout"))
diff --git a/techlibs/anlogic/.gitignore b/techlibs/anlogic/.gitignore
new file mode 100644
index 000000000..d127107db
--- /dev/null
+++ b/techlibs/anlogic/.gitignore
@@ -0,0 +1,2 @@
+brams_init.mk
+brams_init_*.vh
diff --git a/techlibs/anlogic/Makefile.inc b/techlibs/anlogic/Makefile.inc
index 2d8d65e2e..79519c645 100644
--- a/techlibs/anlogic/Makefile.inc
+++ b/techlibs/anlogic/Makefile.inc
@@ -3,6 +3,22 @@ OBJS += techlibs/anlogic/synth_anlogic.o
OBJS += techlibs/anlogic/anlogic_eqn.o
OBJS += techlibs/anlogic/anlogic_fixcarry.o
+GENFILES += techlibs/anlogic/brams_init_16.vh
+GENFILES += techlibs/anlogic/brams_init_9.vh
+GENFILES += techlibs/anlogic/brams_init_8.vh
+
+EXTRA_OBJS += techlibs/anlogic/brams_init.mk
+.SECONDARY: techlibs/anlogic/brams_init.mk
+
+techlibs/anlogic/brams_init.mk: techlibs/anlogic/brams_init.py
+ $(Q) mkdir -p techlibs/anlogic
+ $(P) $(PYTHON_EXECUTABLE) $<
+ $(Q) touch $@
+
+techlibs/anlogic/brams_init_16.vh: techlibs/anlogic/brams_init.mk
+techlibs/anlogic/brams_init_9.vh: techlibs/anlogic/brams_init.mk
+techlibs/anlogic/brams_init_8.vh: techlibs/anlogic/brams_init.mk
+
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v))
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v))
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_sim.v))
@@ -10,3 +26,9 @@ $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/eagle_bb.v))
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutrams.txt))
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutrams_map.v))
$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutram_init_16x4.vh))
+$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/brams.txt))
+$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/brams_map.v))
+
+$(eval $(call add_gen_share_file,share/anlogic,techlibs/anlogic/brams_init_16.vh))
+$(eval $(call add_gen_share_file,share/anlogic,techlibs/anlogic/brams_init_9.vh))
+$(eval $(call add_gen_share_file,share/anlogic,techlibs/anlogic/brams_init_8.vh))
diff --git a/techlibs/anlogic/anlogic_eqn.cc b/techlibs/anlogic/anlogic_eqn.cc
index e5fbc186f..4004b9f17 100644
--- a/techlibs/anlogic/anlogic_eqn.cc
+++ b/techlibs/anlogic/anlogic_eqn.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
+ * Copyright (C) 2018 Miodrag Milanovic <micko@yosyshq.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
diff --git a/techlibs/anlogic/anlogic_fixcarry.cc b/techlibs/anlogic/anlogic_fixcarry.cc
index c7dfe3c05..e8d061b93 100644
--- a/techlibs/anlogic/anlogic_fixcarry.cc
+++ b/techlibs/anlogic/anlogic_fixcarry.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
+ * Copyright (C) 2019 Miodrag Milanovic <micko@yosyshq.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
diff --git a/techlibs/anlogic/arith_map.v b/techlibs/anlogic/arith_map.v
index 23e190bcb..f0cec4909 100644
--- a/techlibs/anlogic/arith_map.v
+++ b/techlibs/anlogic/arith_map.v
@@ -1,8 +1,8 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 Miodrag Milanovic <micko@yosyshq.com>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/anlogic/brams.txt b/techlibs/anlogic/brams.txt
new file mode 100644
index 000000000..a39701c63
--- /dev/null
+++ b/techlibs/anlogic/brams.txt
@@ -0,0 +1,43 @@
+bram $__ANLOGIC_BRAM9K_TDP
+ init 1
+ abits 13 @a13d1
+ dbits 1 @a13d1
+ abits 12 @a12d2
+ dbits 2 @a12d2
+ abits 11 @a11d4
+ dbits 4 @a11d4
+ abits 10 @a10d9
+ dbits 9 @a10d9
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 1 1
+ transp 2 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+bram $__ANLOGIC_BRAM32K
+ init 1
+ abits 11
+ dbits 16
+ groups 2
+ ports 1 1
+ wrmode 0 1
+ enable 1 2
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+match $__ANLOGIC_BRAM32K
+ min efficiency 30
+ shuffle_enable B
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__ANLOGIC_BRAM9K_TDP
+ min efficiency 5
+ make_transp
+endmatch
diff --git a/techlibs/anlogic/brams_init.py b/techlibs/anlogic/brams_init.py
new file mode 100644
index 000000000..8dda0d33e
--- /dev/null
+++ b/techlibs/anlogic/brams_init.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python3
+
+with open("techlibs/anlogic/brams_init_9.vh", "w") as f:
+ for i in range(4):
+ init_snippets = [" INIT[%3d*9+8]" % (k+256*i,) for k in range(255, -1, -1)]
+ for k in range(4, 256, 4):
+ init_snippets[k] = "\n " + init_snippets[k]
+ print(".INITP_%02X({%s})," % (i, ",".join(init_snippets)), file=f)
+ for i in range(32):
+ init_snippets = [" INIT[%3d*9 +: 8]" % (k+32*i,) for k in range(31, -1, -1)]
+ for k in range(4, 32, 4):
+ init_snippets[k] = "\n " + init_snippets[k]
+ print(".INIT_%02X({%s})," % (i, ",".join(init_snippets)), file=f)
+
+with open("techlibs/anlogic/brams_init_8.vh", "w") as f:
+ for i in range(32):
+ print(".INIT_%02X(INIT[%3d*256 +: 256])," % (i, i), file=f)
+
+with open("techlibs/anlogic/brams_init_16.vh", "w") as f:
+ for i in range(128):
+ print(".INIT_%02X(INIT[%3d*256 +: 256])," % (i, i), file=f)
diff --git a/techlibs/anlogic/brams_map.v b/techlibs/anlogic/brams_map.v
new file mode 100644
index 000000000..ee02b6d7c
--- /dev/null
+++ b/techlibs/anlogic/brams_map.v
@@ -0,0 +1,162 @@
+module \$__ANLOGIC_BRAM9K_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 10;
+ parameter CFG_DBITS = 9;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+ parameter [9215:0] INIT = 9216'bx;
+ parameter TRANSP2 = 0;
+
+ input CLK2;
+ input CLK3;
+
+ input [CFG_ABITS-1:0] A1ADDR;
+ output [CFG_DBITS-1:0] A1DATA;
+ input A1EN;
+
+ input [CFG_ABITS-1:0] B1ADDR;
+ input [CFG_DBITS-1:0] B1DATA;
+ input B1EN;
+
+ localparam CLKAMUX = CLKPOL2 ? "SIG" : "INV";
+ localparam CLKBMUX = CLKPOL3 ? "SIG" : "INV";
+
+ localparam WRITEMODE_B = TRANSP2 ? "WRITETHROUGH" : "READBEFOREWRITE";
+
+ localparam DATA_WIDTH = CFG_DBITS == 1 ? "1" :
+ (CFG_DBITS == 2 ? "2" :
+ (CFG_DBITS <= 4 ? "4" : "9"));
+
+ localparam APADBITS = $clog2(CFG_DBITS == 9 ? 8 : CFG_DBITS);
+
+ wire [12:0] addra;
+ wire [12:0] addrb;
+
+ assign addra[12:APADBITS] = A1ADDR;
+ assign addrb[12:APADBITS] = B1ADDR;
+
+ wire [8:0] doa;
+ wire [8:0] dib;
+
+ assign A1DATA[CFG_DBITS-1:0] = doa;
+ assign dib[CFG_DBITS-1:0] = B1DATA;
+
+ generate if (CFG_DBITS == 9) begin
+ EG_PHY_BRAM #(
+ .MODE("DP8K"),
+ .DATA_WIDTH_A(DATA_WIDTH),
+ .DATA_WIDTH_B(DATA_WIDTH),
+ .READBACK("OFF"),
+ .REGMODE_A("NOREG"),
+ .REGMODE_B("NOREG"),
+ .WRITEMODE_A("READBEFOREWRITE"),
+ .WRITEMODE_B(WRITEMODE_B),
+ .RESETMODE("ASYNC"),
+ .CEAMUX("SIG"), .CEBMUX("SIG"),
+ .OCEAMUX("1"), .OCEBMUX("1"),
+ .RSTAMUX("0"), .RSTBMUX("0"),
+ .CLKAMUX(CLKAMUX),
+ .CLKBMUX(CLKBMUX),
+ .WEAMUX("0"), .WEBMUX("SIG"),
+ .CSA0("1"), .CSA1("1"),
+ .CSA2("1"), .CSB0("1"),
+ .CSB1("1"), .CSB2("1"),
+ `include "brams_init_9.vh"
+ ) _TECHMAP_REPLACE_ (
+ .doa(doa), .dib(dib),
+ .addra(addra), .addrb(addrb),
+ .clka(CLK2), .clkb(CLK3),
+ .cea(A1EN), .ceb(B1EN),
+ .ocea(1'b1), .oceb(1'b1),
+ .rsta(1'b0), .rstb(1'b0),
+ .wea(1'b0), .web(B1EN),
+ .csa(3'b111), .csb(3'b111)
+ );
+ end else begin
+ EG_PHY_BRAM #(
+ .MODE("DP8K"),
+ .DATA_WIDTH_A(DATA_WIDTH),
+ .DATA_WIDTH_B(DATA_WIDTH),
+ .READBACK("OFF"),
+ .REGMODE_A("NOREG"),
+ .REGMODE_B("NOREG"),
+ .WRITEMODE_A("READBEFOREWRITE"),
+ .WRITEMODE_B(WRITEMODE_B),
+ .RESETMODE("ASYNC"),
+ .CEAMUX("SIG"), .CEBMUX("SIG"),
+ .OCEAMUX("1"), .OCEBMUX("1"),
+ .RSTAMUX("0"), .RSTBMUX("0"),
+ .CLKAMUX(CLKAMUX),
+ .CLKBMUX(CLKBMUX),
+ .WEAMUX("0"), .WEBMUX("SIG"),
+ .CSA0("1"), .CSA1("1"),
+ .CSA2("1"), .CSB0("1"),
+ .CSB1("1"), .CSB2("1"),
+ `include "brams_init_8.vh"
+ ) _TECHMAP_REPLACE_ (
+ .doa(doa), .dib(dib),
+ .addra(addra), .addrb(addrb),
+ .clka(CLK2), .clkb(CLK3),
+ .cea(A1EN), .ceb(B1EN),
+ .ocea(1'b1), .oceb(1'b1),
+ .rsta(1'b0), .rstb(1'b0),
+ .wea(1'b0), .web(B1EN),
+ .csa(3'b111), .csb(3'b111)
+ );
+ end endgenerate
+endmodule
+
+module \$__ANLOGIC_BRAM32K (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 11;
+ parameter CFG_DBITS = 16;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+ parameter [32767:0] INIT = 32768'bx;
+
+ input CLK2;
+ input CLK3;
+
+ input [CFG_ABITS-1:0] A1ADDR;
+ output [CFG_DBITS-1:0] A1DATA;
+ input A1EN;
+
+ input [CFG_ABITS-1:0] B1ADDR;
+ input [CFG_DBITS-1:0] B1DATA;
+ input [1:0] B1EN;
+
+ localparam CLKAMUX = CLKPOL2 ? "SIG" : "INV";
+ localparam CLKBMUX = CLKPOL3 ? "SIG" : "INV";
+
+ wire byteweb = B1EN[1] ^ B1EN[0];
+ wire byteb = B1EN[1];
+
+ EG_PHY_BRAM32K #(
+ .MODE("DP16K"),
+ .DATA_WIDTH_A("16"),
+ .DATA_WIDTH_B("16"),
+ .REGMODE_A("NOREG"),
+ .REGMODE_B("NOREG"),
+ .WRITEMODE_A("NORMAL"),
+ .WRITEMODE_B("NORMAL"),
+ .SRMODE("ASYNC"),
+ .CSAMUX("SIG"), .CSBMUX("SIG"),
+ .OCEAMUX("1"), .OCEBMUX("1"),
+ .RSTAMUX("0"), .RSTBMUX("0"),
+ .CLKAMUX(CLKAMUX),
+ .CLKBMUX(CLKBMUX),
+ .WEAMUX("0"), .WEBMUX("SIG"),
+ .READBACK("OFF"),
+ `include "brams_init_16.vh"
+ ) _TECHMAP_REPLACE_ (
+ .doa(A1DATA), .dib(B1DATA),
+ .addra(A1ADDR), .addrb(B1ADDR),
+ .bytea(1'b0), .byteb(byteb),
+ .bytewea(1'b0), .byteweb(byteweb),
+ .csa(A1EN), .csb(|B1EN),
+ .wea(1'b0), .web(|B1EN),
+ .clka(CLK2), .clkb(CLK3),
+ .rsta(1'b0), .rstb(1'b0),
+ .ocea(1'b1), .oceb(1'b1)
+ );
+endmodule
diff --git a/techlibs/anlogic/synth_anlogic.cc b/techlibs/anlogic/synth_anlogic.cc
index d953fae5e..5da14c26b 100644
--- a/techlibs/anlogic/synth_anlogic.cc
+++ b/techlibs/anlogic/synth_anlogic.cc
@@ -1,8 +1,8 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
- * Copyright (C) 2018 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 Miodrag Milanovic <micko@yosyshq.com>
+ * Copyright (C) 2018 Claire Xenia Wolf <claire@yosyshq.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
@@ -63,6 +63,9 @@ struct SynthAnlogicPass : public ScriptPass
log(" -nolutram\n");
log(" do not use EG_LOGIC_DRAM16X4 cells in output netlist\n");
log("\n");
+ log(" -nobram\n");
+ log(" do not use EG_PHY_BRAM or EG_PHY_BRAM32K cells in output netlist\n");
+ log("\n");
log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
@@ -70,7 +73,7 @@ struct SynthAnlogicPass : public ScriptPass
}
string top_opt, edif_file, json_file;
- bool flatten, retime, nolutram;
+ bool flatten, retime, nolutram, nobram;
void clear_flags() override
{
@@ -80,6 +83,7 @@ struct SynthAnlogicPass : public ScriptPass
flatten = true;
retime = false;
nolutram = false;
+ nobram = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -118,6 +122,10 @@ struct SynthAnlogicPass : public ScriptPass
nolutram = true;
continue;
}
+ if (args[argidx] == "-nobram") {
+ nobram = true;
+ continue;
+ }
if (args[argidx] == "-retime") {
retime = true;
continue;
@@ -158,6 +166,14 @@ struct SynthAnlogicPass : public ScriptPass
run("synth -run coarse");
}
+ if (!nobram && check_label("map_bram", "(skip if -nobram)"))
+ {
+ run("memory_bram -rules +/anlogic/brams.txt");
+ run("techmap -map +/anlogic/brams_map.v");
+ run("setundef -zero -params t:EG_PHY_BRAM");
+ run("setundef -zero -params t:EG_PHY_BRAM32K");
+ }
+
if (!nolutram && check_label("map_lutram", "(skip if -nolutram)"))
{
run("memory_bram -rules +/anlogic/lutrams.txt");
@@ -211,6 +227,7 @@ struct SynthAnlogicPass : public ScriptPass
run("hierarchy -check");
run("stat");
run("check -noinit");
+ run("blackbox =A:whitebox");
}
if (check_label("edif"))
diff --git a/techlibs/common/abc9_model.v b/techlibs/common/abc9_model.v
index 4fee60f75..570a1ec40 100644
--- a/techlibs/common/abc9_model.v
+++ b/techlibs/common/abc9_model.v
@@ -6,6 +6,10 @@ module $__ABC9_DELAY (input I, output O);
endspecify
endmodule
+module $__ABC9_SCC_BREAKER (input [WIDTH-1:0] I, output [WIDTH-1:0] O);
+parameter WIDTH = 0;
+endmodule
+
(* abc9_flop, abc9_box, lib_whitebox *)
module $__DFF_N__$abc9_flop (input C, D, Q, output n1);
assign n1 = D;
diff --git a/techlibs/common/abc9_unmap.v b/techlibs/common/abc9_unmap.v
index c39648c62..b1bc4fb6e 100644
--- a/techlibs/common/abc9_unmap.v
+++ b/techlibs/common/abc9_unmap.v
@@ -9,3 +9,8 @@ module $__DFF_x__$abc9_flop (input C, D, (* init = 1'b0 *) input Q, output n1);
$error("Unrecognised _TECHMAP_CELLTYPE_");
endgenerate
endmodule
+
+module $__ABC9_SCC_BREAKER (input [WIDTH-1:0] I, output [WIDTH-1:0] O);
+parameter WIDTH = 0;
+assign O = I;
+endmodule
diff --git a/techlibs/common/gen_fine_ffs.py b/techlibs/common/gen_fine_ffs.py
index 5d331e767..25c6ef171 100644
--- a/techlibs/common/gen_fine_ffs.py
+++ b/techlibs/common/gen_fine_ffs.py
@@ -133,6 +133,55 @@ endmodule
"""
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
+//- $_ALDFF_{C:N|P}{L:N|P}_ (D, C, L, AD, Q)
+//-
+//- A {C:negative|positive} edge D-type flip-flop with {L:negative|positive} polarity async load.
+//-
+//- Truth table: D C L AD | Q
+//- ----------+---
+//- - - {L:0|1} a | a
+//- d {C:\\|/} - - | d
+//- - - - - | q
+//-
+module \$_ALDFF_{C:N|P}{L:N|P}_ (D, C, L, AD, Q);
+input D, C, L, AD;
+output reg Q;
+always @({C:neg|pos}edge C or {L:neg|pos}edge L) begin
+ if (L == {L:0|1})
+ Q <= AD;
+ else
+ Q <= D;
+end
+endmodule
+""",
+"""
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_{C:N|P}{L:N|P}{E:N|P}_ (D, C, L, AD, E, Q)
+//-
+//- A {C:negative|positive} edge D-type flip-flop with {L:negative|positive} polarity async load and {E:negative|positive}
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - {L:0|1} a - | a
+//- d {C:\\|/} - - {E:0|1} | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_{C:N|P}{L:N|P}{E:N|P}_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @({C:neg|pos}edge C or {L:neg|pos}edge L) begin
+ if (L == {L:0|1})
+ Q <= AD;
+ else if (E == {E:0|1})
+ Q <= D;
+end
+endmodule
+""",
+"""
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
//- $_DFFSR_{C:N|P}{S:N|P}{R:N|P}_ (C, S, R, D, Q)
//-
//- A {C:negative|positive} edge D-type flip-flop with {S:negative|positive} polarity set and {R:negative|positive}
diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v
index f22f47b4a..ca2b3c5cf 100644
--- a/techlibs/common/mul2dsp.v
+++ b/techlibs/common/mul2dsp.v
@@ -1,318 +1,318 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * 2019 Eddie Hung <eddie@fpgeh.com>
- * 2019 David Shah <dave@ds0.me>
- *
- * 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.
- *
- * ---
- *
- * Tech-mapping rules for decomposing arbitrarily-sized $mul cells
- * into an equivalent collection of smaller `DSP_NAME cells (with the
- * same interface as $mul) no larger than `DSP_[AB]_MAXWIDTH, attached
- * to $shl and $add cells.
- *
- */
-
-`ifndef DSP_A_MAXWIDTH
-$fatal(1, "Macro DSP_A_MAXWIDTH must be defined");
-`endif
-`ifndef DSP_B_MAXWIDTH
-$fatal(1, "Macro DSP_B_MAXWIDTH must be defined");
-`endif
-`ifndef DSP_B_MAXWIDTH
-$fatal(1, "Macro DSP_B_MAXWIDTH must be defined");
-`endif
-`ifndef DSP_A_MAXWIDTH_PARTIAL
-`define DSP_A_MAXWIDTH_PARTIAL `DSP_A_MAXWIDTH
-`endif
-`ifndef DSP_B_MAXWIDTH_PARTIAL
-`define DSP_B_MAXWIDTH_PARTIAL `DSP_B_MAXWIDTH
-`endif
-
-`ifndef DSP_NAME
-$fatal(1, "Macro DSP_NAME must be defined");
-`endif
-
-`define MAX(a,b) (a > b ? a : b)
-`define MIN(a,b) (a < b ? a : b)
-
-(* techmap_celltype = "$mul $__mul" *)
-module _80_mul (A, B, Y);
- parameter A_SIGNED = 0;
- parameter B_SIGNED = 0;
- parameter A_WIDTH = 1;
- parameter B_WIDTH = 1;
- parameter Y_WIDTH = 1;
-
- (* force_downto *)
- input [A_WIDTH-1:0] A;
- (* force_downto *)
- input [B_WIDTH-1:0] B;
- (* force_downto *)
- output [Y_WIDTH-1:0] Y;
-
- parameter _TECHMAP_CELLTYPE_ = "";
-
- generate
- if (0) begin end
-`ifdef DSP_A_MINWIDTH
- else if (A_WIDTH < `DSP_A_MINWIDTH)
- wire _TECHMAP_FAIL_ = 1;
-`endif
-`ifdef DSP_B_MINWIDTH
- else if (B_WIDTH < `DSP_B_MINWIDTH)
- wire _TECHMAP_FAIL_ = 1;
-`endif
-`ifdef DSP_Y_MINWIDTH
- else if (Y_WIDTH < `DSP_Y_MINWIDTH)
- wire _TECHMAP_FAIL_ = 1;
-`endif
-`ifdef DSP_SIGNEDONLY
- else if (_TECHMAP_CELLTYPE_ == "$mul" && !A_SIGNED && !B_SIGNED)
- \$mul #(
- .A_SIGNED(1),
- .B_SIGNED(1),
- .A_WIDTH(A_WIDTH + 1),
- .B_WIDTH(B_WIDTH + 1),
- .Y_WIDTH(Y_WIDTH)
- ) _TECHMAP_REPLACE_ (
- .A({1'b0, A}),
- .B({1'b0, B}),
- .Y(Y)
- );
-`endif
- else if (_TECHMAP_CELLTYPE_ == "$mul" && A_WIDTH < B_WIDTH)
- \$mul #(
- .A_SIGNED(B_SIGNED),
- .B_SIGNED(A_SIGNED),
- .A_WIDTH(B_WIDTH),
- .B_WIDTH(A_WIDTH),
- .Y_WIDTH(Y_WIDTH)
- ) _TECHMAP_REPLACE_ (
- .A(B),
- .B(A),
- .Y(Y)
- );
- else begin
- wire [1023:0] _TECHMAP_DO_ = "proc; clean";
-
-`ifdef DSP_SIGNEDONLY
- localparam sign_headroom = 1;
-`else
- localparam sign_headroom = 0;
-`endif
-
- genvar i;
- if (A_WIDTH > `DSP_A_MAXWIDTH) begin
- localparam n = (A_WIDTH-`DSP_A_MAXWIDTH+`DSP_A_MAXWIDTH_PARTIAL-sign_headroom-1) / (`DSP_A_MAXWIDTH_PARTIAL-sign_headroom);
- localparam partial_Y_WIDTH = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH_PARTIAL);
- localparam last_A_WIDTH = A_WIDTH-n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom);
- localparam last_Y_WIDTH = B_WIDTH+last_A_WIDTH;
- if (A_SIGNED && B_SIGNED) begin : blk
- (* force_downto *)
- wire signed [partial_Y_WIDTH-1:0] partial [n-1:0];
- (* force_downto *)
- wire signed [last_Y_WIDTH-1:0] last_partial;
- (* force_downto *)
- wire signed [Y_WIDTH-1:0] partial_sum [n:0];
- end
- else begin : blk
- (* force_downto *)
- wire [partial_Y_WIDTH-1:0] partial [n-1:0];
- (* force_downto *)
- wire [last_Y_WIDTH-1:0] last_partial;
- (* force_downto *)
- wire [Y_WIDTH-1:0] partial_sum [n:0];
- end
-
- for (i = 0; i < n; i=i+1) begin:sliceA
- \$__mul #(
- .A_SIGNED(sign_headroom),
- .B_SIGNED(B_SIGNED),
- .A_WIDTH(`DSP_A_MAXWIDTH_PARTIAL),
- .B_WIDTH(B_WIDTH),
- .Y_WIDTH(partial_Y_WIDTH)
- ) mul (
- .A({{sign_headroom{1'b0}}, A[i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom) +: `DSP_A_MAXWIDTH_PARTIAL-sign_headroom]}),
- .B(B),
- .Y(blk.partial[i])
- );
- // TODO: Currently a 'cascade' approach to summing the partial
- // products is taken here, but a more efficient 'binary
- // reduction' approach also exists...
- if (i == 0)
- assign blk.partial_sum[i] = blk.partial[i];
- else
- assign blk.partial_sum[i] = (blk.partial[i] << (* mul2dsp *) i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[i-1];
- end
-
- \$__mul #(
- .A_SIGNED(A_SIGNED),
- .B_SIGNED(B_SIGNED),
- .A_WIDTH(last_A_WIDTH),
- .B_WIDTH(B_WIDTH),
- .Y_WIDTH(last_Y_WIDTH)
- ) sliceA.last (
- .A(A[A_WIDTH-1 -: last_A_WIDTH]),
- .B(B),
- .Y(blk.last_partial)
- );
- assign blk.partial_sum[n] = (blk.last_partial << (* mul2dsp *) n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[n-1];
- assign Y = blk.partial_sum[n];
- end
- else if (B_WIDTH > `DSP_B_MAXWIDTH) begin
- localparam n = (B_WIDTH-`DSP_B_MAXWIDTH+`DSP_B_MAXWIDTH_PARTIAL-sign_headroom-1) / (`DSP_B_MAXWIDTH_PARTIAL-sign_headroom);
- localparam partial_Y_WIDTH = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH_PARTIAL);
- localparam last_B_WIDTH = B_WIDTH-n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom);
- localparam last_Y_WIDTH = A_WIDTH+last_B_WIDTH;
- if (A_SIGNED && B_SIGNED) begin : blk
- (* force_downto *)
- wire signed [partial_Y_WIDTH-1:0] partial [n-1:0];
- (* force_downto *)
- wire signed [last_Y_WIDTH-1:0] last_partial;
- (* force_downto *)
- wire signed [Y_WIDTH-1:0] partial_sum [n:0];
- end
- else begin : blk
- (* force_downto *)
- wire [partial_Y_WIDTH-1:0] partial [n-1:0];
- (* force_downto *)
- wire [last_Y_WIDTH-1:0] last_partial;
- (* force_downto *)
- wire [Y_WIDTH-1:0] partial_sum [n:0];
- end
-
- for (i = 0; i < n; i=i+1) begin:sliceB
- \$__mul #(
- .A_SIGNED(A_SIGNED),
- .B_SIGNED(sign_headroom),
- .A_WIDTH(A_WIDTH),
- .B_WIDTH(`DSP_B_MAXWIDTH_PARTIAL),
- .Y_WIDTH(partial_Y_WIDTH)
- ) mul (
- .A(A),
- .B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom) +: `DSP_B_MAXWIDTH_PARTIAL-sign_headroom]}),
- .Y(blk.partial[i])
- );
- // TODO: Currently a 'cascade' approach to summing the partial
- // products is taken here, but a more efficient 'binary
- // reduction' approach also exists...
- if (i == 0)
- assign blk.partial_sum[i] = blk.partial[i];
- else
- assign blk.partial_sum[i] = (blk.partial[i] << (* mul2dsp *) i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[i-1];
- end
-
- \$__mul #(
- .A_SIGNED(A_SIGNED),
- .B_SIGNED(B_SIGNED),
- .A_WIDTH(A_WIDTH),
- .B_WIDTH(last_B_WIDTH),
- .Y_WIDTH(last_Y_WIDTH)
- ) mul_sliceB_last (
- .A(A),
- .B(B[B_WIDTH-1 -: last_B_WIDTH]),
- .Y(blk.last_partial)
- );
- assign blk.partial_sum[n] = (blk.last_partial << (* mul2dsp *) n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[n-1];
- assign Y = blk.partial_sum[n];
- end
- else begin
- if (A_SIGNED) begin : blkA
- wire signed [`DSP_A_MAXWIDTH-1:0] Aext = $signed(A);
- end
- else begin : blkA
- wire [`DSP_A_MAXWIDTH-1:0] Aext = A;
- end
- if (B_SIGNED) begin : blkB
- wire signed [`DSP_B_MAXWIDTH-1:0] Bext = $signed(B);
- end
- else begin : blkB
- wire [`DSP_B_MAXWIDTH-1:0] Bext = B;
- end
-
- `DSP_NAME #(
- .A_SIGNED(A_SIGNED),
- .B_SIGNED(B_SIGNED),
- .A_WIDTH(`DSP_A_MAXWIDTH),
- .B_WIDTH(`DSP_B_MAXWIDTH),
- .Y_WIDTH(`MIN(Y_WIDTH,`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH)),
- ) _TECHMAP_REPLACE_ (
- .A(blkA.Aext),
- .B(blkB.Bext),
- .Y(Y)
- );
- end
- end
- endgenerate
-endmodule
-
-(* techmap_celltype = "$mul $__mul" *)
-module _90_soft_mul (A, B, Y);
- parameter A_SIGNED = 0;
- parameter B_SIGNED = 0;
- parameter A_WIDTH = 1;
- parameter B_WIDTH = 1;
- parameter Y_WIDTH = 1;
-
- (* force_downto *)
- input [A_WIDTH-1:0] A;
- (* force_downto *)
- input [B_WIDTH-1:0] B;
- (* force_downto *)
- output [Y_WIDTH-1:0] Y;
-
- // Indirection necessary since mapping
- // back to $mul will cause recursion
- generate
- if (A_SIGNED && !B_SIGNED)
- \$__soft_mul #(
- .A_SIGNED(A_SIGNED),
- .B_SIGNED(1),
- .A_WIDTH(A_WIDTH),
- .B_WIDTH(B_WIDTH+1),
- .Y_WIDTH(Y_WIDTH)
- ) _TECHMAP_REPLACE_ (
- .A(A),
- .B({1'b0,B}),
- .Y(Y)
- );
- else if (!A_SIGNED && B_SIGNED)
- \$__soft_mul #(
- .A_SIGNED(1),
- .B_SIGNED(B_SIGNED),
- .A_WIDTH(A_WIDTH+1),
- .B_WIDTH(B_WIDTH),
- .Y_WIDTH(Y_WIDTH)
- ) _TECHMAP_REPLACE_ (
- .A({1'b0,A}),
- .B(B),
- .Y(Y)
- );
- else
- \$__soft_mul #(
- .A_SIGNED(A_SIGNED),
- .B_SIGNED(B_SIGNED),
- .A_WIDTH(A_WIDTH),
- .B_WIDTH(B_WIDTH),
- .Y_WIDTH(Y_WIDTH)
- ) _TECHMAP_REPLACE_ (
- .A(A),
- .B(B),
- .Y(Y)
- );
- endgenerate
-endmodule
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
+ * 2019 Eddie Hung <eddie@fpgeh.com>
+ * 2019 gatecat <gatecat@ds0.me>
+ *
+ * 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.
+ *
+ * ---
+ *
+ * Tech-mapping rules for decomposing arbitrarily-sized $mul cells
+ * into an equivalent collection of smaller `DSP_NAME cells (with the
+ * same interface as $mul) no larger than `DSP_[AB]_MAXWIDTH, attached
+ * to $shl and $add cells.
+ *
+ */
+
+`ifndef DSP_A_MAXWIDTH
+$fatal(1, "Macro DSP_A_MAXWIDTH must be defined");
+`endif
+`ifndef DSP_B_MAXWIDTH
+$fatal(1, "Macro DSP_B_MAXWIDTH must be defined");
+`endif
+`ifndef DSP_B_MAXWIDTH
+$fatal(1, "Macro DSP_B_MAXWIDTH must be defined");
+`endif
+`ifndef DSP_A_MAXWIDTH_PARTIAL
+`define DSP_A_MAXWIDTH_PARTIAL `DSP_A_MAXWIDTH
+`endif
+`ifndef DSP_B_MAXWIDTH_PARTIAL
+`define DSP_B_MAXWIDTH_PARTIAL `DSP_B_MAXWIDTH
+`endif
+
+`ifndef DSP_NAME
+$fatal(1, "Macro DSP_NAME must be defined");
+`endif
+
+`define MAX(a,b) (a > b ? a : b)
+`define MIN(a,b) (a < b ? a : b)
+
+(* techmap_celltype = "$mul $__mul" *)
+module _80_mul (A, B, Y);
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+ parameter A_WIDTH = 1;
+ parameter B_WIDTH = 1;
+ parameter Y_WIDTH = 1;
+
+ (* force_downto *)
+ input [A_WIDTH-1:0] A;
+ (* force_downto *)
+ input [B_WIDTH-1:0] B;
+ (* force_downto *)
+ output [Y_WIDTH-1:0] Y;
+
+ parameter _TECHMAP_CELLTYPE_ = "";
+
+ generate
+ if (0) begin end
+`ifdef DSP_A_MINWIDTH
+ else if (A_WIDTH < `DSP_A_MINWIDTH)
+ wire _TECHMAP_FAIL_ = 1;
+`endif
+`ifdef DSP_B_MINWIDTH
+ else if (B_WIDTH < `DSP_B_MINWIDTH)
+ wire _TECHMAP_FAIL_ = 1;
+`endif
+`ifdef DSP_Y_MINWIDTH
+ else if (Y_WIDTH < `DSP_Y_MINWIDTH)
+ wire _TECHMAP_FAIL_ = 1;
+`endif
+`ifdef DSP_SIGNEDONLY
+ else if (_TECHMAP_CELLTYPE_ == "$mul" && !A_SIGNED && !B_SIGNED)
+ \$mul #(
+ .A_SIGNED(1),
+ .B_SIGNED(1),
+ .A_WIDTH(A_WIDTH + 1),
+ .B_WIDTH(B_WIDTH + 1),
+ .Y_WIDTH(Y_WIDTH)
+ ) _TECHMAP_REPLACE_ (
+ .A({1'b0, A}),
+ .B({1'b0, B}),
+ .Y(Y)
+ );
+`endif
+ else if (_TECHMAP_CELLTYPE_ == "$mul" && A_WIDTH < B_WIDTH)
+ \$mul #(
+ .A_SIGNED(B_SIGNED),
+ .B_SIGNED(A_SIGNED),
+ .A_WIDTH(B_WIDTH),
+ .B_WIDTH(A_WIDTH),
+ .Y_WIDTH(Y_WIDTH)
+ ) _TECHMAP_REPLACE_ (
+ .A(B),
+ .B(A),
+ .Y(Y)
+ );
+ else begin
+ wire [1023:0] _TECHMAP_DO_ = "proc; clean";
+
+`ifdef DSP_SIGNEDONLY
+ localparam sign_headroom = 1;
+`else
+ localparam sign_headroom = 0;
+`endif
+
+ genvar i;
+ if (A_WIDTH > `DSP_A_MAXWIDTH) begin
+ localparam n = (A_WIDTH-`DSP_A_MAXWIDTH+`DSP_A_MAXWIDTH_PARTIAL-sign_headroom-1) / (`DSP_A_MAXWIDTH_PARTIAL-sign_headroom);
+ localparam partial_Y_WIDTH = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH_PARTIAL);
+ localparam last_A_WIDTH = A_WIDTH-n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom);
+ localparam last_Y_WIDTH = B_WIDTH+last_A_WIDTH;
+ if (A_SIGNED && B_SIGNED) begin : blk
+ (* force_downto *)
+ wire signed [partial_Y_WIDTH-1:0] partial [n-1:0];
+ (* force_downto *)
+ wire signed [last_Y_WIDTH-1:0] last_partial;
+ (* force_downto *)
+ wire signed [Y_WIDTH-1:0] partial_sum [n:0];
+ end
+ else begin : blk
+ (* force_downto *)
+ wire [partial_Y_WIDTH-1:0] partial [n-1:0];
+ (* force_downto *)
+ wire [last_Y_WIDTH-1:0] last_partial;
+ (* force_downto *)
+ wire [Y_WIDTH-1:0] partial_sum [n:0];
+ end
+
+ for (i = 0; i < n; i=i+1) begin:sliceA
+ \$__mul #(
+ .A_SIGNED(sign_headroom),
+ .B_SIGNED(B_SIGNED),
+ .A_WIDTH(`DSP_A_MAXWIDTH_PARTIAL),
+ .B_WIDTH(B_WIDTH),
+ .Y_WIDTH(partial_Y_WIDTH)
+ ) mul (
+ .A({{sign_headroom{1'b0}}, A[i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom) +: `DSP_A_MAXWIDTH_PARTIAL-sign_headroom]}),
+ .B(B),
+ .Y(blk.partial[i])
+ );
+ // TODO: Currently a 'cascade' approach to summing the partial
+ // products is taken here, but a more efficient 'binary
+ // reduction' approach also exists...
+ if (i == 0)
+ assign blk.partial_sum[i] = blk.partial[i];
+ else
+ assign blk.partial_sum[i] = (blk.partial[i] << (* mul2dsp *) i*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[i-1];
+ end
+
+ \$__mul #(
+ .A_SIGNED(A_SIGNED),
+ .B_SIGNED(B_SIGNED),
+ .A_WIDTH(last_A_WIDTH),
+ .B_WIDTH(B_WIDTH),
+ .Y_WIDTH(last_Y_WIDTH)
+ ) sliceA.last (
+ .A(A[A_WIDTH-1 -: last_A_WIDTH]),
+ .B(B),
+ .Y(blk.last_partial)
+ );
+ assign blk.partial_sum[n] = (blk.last_partial << (* mul2dsp *) n*(`DSP_A_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[n-1];
+ assign Y = blk.partial_sum[n];
+ end
+ else if (B_WIDTH > `DSP_B_MAXWIDTH) begin
+ localparam n = (B_WIDTH-`DSP_B_MAXWIDTH+`DSP_B_MAXWIDTH_PARTIAL-sign_headroom-1) / (`DSP_B_MAXWIDTH_PARTIAL-sign_headroom);
+ localparam partial_Y_WIDTH = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH_PARTIAL);
+ localparam last_B_WIDTH = B_WIDTH-n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom);
+ localparam last_Y_WIDTH = A_WIDTH+last_B_WIDTH;
+ if (A_SIGNED && B_SIGNED) begin : blk
+ (* force_downto *)
+ wire signed [partial_Y_WIDTH-1:0] partial [n-1:0];
+ (* force_downto *)
+ wire signed [last_Y_WIDTH-1:0] last_partial;
+ (* force_downto *)
+ wire signed [Y_WIDTH-1:0] partial_sum [n:0];
+ end
+ else begin : blk
+ (* force_downto *)
+ wire [partial_Y_WIDTH-1:0] partial [n-1:0];
+ (* force_downto *)
+ wire [last_Y_WIDTH-1:0] last_partial;
+ (* force_downto *)
+ wire [Y_WIDTH-1:0] partial_sum [n:0];
+ end
+
+ for (i = 0; i < n; i=i+1) begin:sliceB
+ \$__mul #(
+ .A_SIGNED(A_SIGNED),
+ .B_SIGNED(sign_headroom),
+ .A_WIDTH(A_WIDTH),
+ .B_WIDTH(`DSP_B_MAXWIDTH_PARTIAL),
+ .Y_WIDTH(partial_Y_WIDTH)
+ ) mul (
+ .A(A),
+ .B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom) +: `DSP_B_MAXWIDTH_PARTIAL-sign_headroom]}),
+ .Y(blk.partial[i])
+ );
+ // TODO: Currently a 'cascade' approach to summing the partial
+ // products is taken here, but a more efficient 'binary
+ // reduction' approach also exists...
+ if (i == 0)
+ assign blk.partial_sum[i] = blk.partial[i];
+ else
+ assign blk.partial_sum[i] = (blk.partial[i] << (* mul2dsp *) i*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[i-1];
+ end
+
+ \$__mul #(
+ .A_SIGNED(A_SIGNED),
+ .B_SIGNED(B_SIGNED),
+ .A_WIDTH(A_WIDTH),
+ .B_WIDTH(last_B_WIDTH),
+ .Y_WIDTH(last_Y_WIDTH)
+ ) mul_sliceB_last (
+ .A(A),
+ .B(B[B_WIDTH-1 -: last_B_WIDTH]),
+ .Y(blk.last_partial)
+ );
+ assign blk.partial_sum[n] = (blk.last_partial << (* mul2dsp *) n*(`DSP_B_MAXWIDTH_PARTIAL-sign_headroom)) + (* mul2dsp *) blk.partial_sum[n-1];
+ assign Y = blk.partial_sum[n];
+ end
+ else begin
+ if (A_SIGNED) begin : blkA
+ wire signed [`DSP_A_MAXWIDTH-1:0] Aext = $signed(A);
+ end
+ else begin : blkA
+ wire [`DSP_A_MAXWIDTH-1:0] Aext = A;
+ end
+ if (B_SIGNED) begin : blkB
+ wire signed [`DSP_B_MAXWIDTH-1:0] Bext = $signed(B);
+ end
+ else begin : blkB
+ wire [`DSP_B_MAXWIDTH-1:0] Bext = B;
+ end
+
+ `DSP_NAME #(
+ .A_SIGNED(A_SIGNED),
+ .B_SIGNED(B_SIGNED),
+ .A_WIDTH(`DSP_A_MAXWIDTH),
+ .B_WIDTH(`DSP_B_MAXWIDTH),
+ .Y_WIDTH(`MIN(Y_WIDTH,`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH)),
+ ) _TECHMAP_REPLACE_ (
+ .A(blkA.Aext),
+ .B(blkB.Bext),
+ .Y(Y)
+ );
+ end
+ end
+ endgenerate
+endmodule
+
+(* techmap_celltype = "$mul $__mul" *)
+module _90_soft_mul (A, B, Y);
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+ parameter A_WIDTH = 1;
+ parameter B_WIDTH = 1;
+ parameter Y_WIDTH = 1;
+
+ (* force_downto *)
+ input [A_WIDTH-1:0] A;
+ (* force_downto *)
+ input [B_WIDTH-1:0] B;
+ (* force_downto *)
+ output [Y_WIDTH-1:0] Y;
+
+ // Indirection necessary since mapping
+ // back to $mul will cause recursion
+ generate
+ if (A_SIGNED && !B_SIGNED)
+ \$__soft_mul #(
+ .A_SIGNED(A_SIGNED),
+ .B_SIGNED(1),
+ .A_WIDTH(A_WIDTH),
+ .B_WIDTH(B_WIDTH+1),
+ .Y_WIDTH(Y_WIDTH)
+ ) _TECHMAP_REPLACE_ (
+ .A(A),
+ .B({1'b0,B}),
+ .Y(Y)
+ );
+ else if (!A_SIGNED && B_SIGNED)
+ \$__soft_mul #(
+ .A_SIGNED(1),
+ .B_SIGNED(B_SIGNED),
+ .A_WIDTH(A_WIDTH+1),
+ .B_WIDTH(B_WIDTH),
+ .Y_WIDTH(Y_WIDTH)
+ ) _TECHMAP_REPLACE_ (
+ .A({1'b0,A}),
+ .B(B),
+ .Y(Y)
+ );
+ else
+ \$__soft_mul #(
+ .A_SIGNED(A_SIGNED),
+ .B_SIGNED(B_SIGNED),
+ .A_WIDTH(A_WIDTH),
+ .B_WIDTH(B_WIDTH),
+ .Y_WIDTH(Y_WIDTH)
+ ) _TECHMAP_REPLACE_ (
+ .A(A),
+ .B(B),
+ .Y(Y)
+ );
+ endgenerate
+endmodule
diff --git a/techlibs/common/prep.cc b/techlibs/common/prep.cc
index 93b0910d6..c354956bc 100644
--- a/techlibs/common/prep.cc
+++ b/techlibs/common/prep.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -61,7 +61,7 @@ struct PrepPass : public ScriptPass
log(" do not run any of the memory_* passes\n");
log("\n");
log(" -rdff\n");
- log(" do not pass -nordff to 'memory_dff'. This enables merging of FFs into\n");
+ log(" call 'memory_dff'. This enables merging of FFs into\n");
log(" memory read ports.\n");
log("\n");
log(" -nokeepdc\n");
@@ -79,7 +79,7 @@ struct PrepPass : public ScriptPass
}
string top_module, fsm_opts;
- bool autotop, flatten, ifxmode, memxmode, nomemmode, nokeepdc, nordff;
+ bool autotop, flatten, ifxmode, memxmode, nomemmode, nokeepdc, rdff;
void clear_flags() override
{
@@ -91,7 +91,7 @@ struct PrepPass : public ScriptPass
memxmode = false;
nomemmode = false;
nokeepdc = false;
- nordff = true;
+ rdff = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -137,11 +137,11 @@ struct PrepPass : public ScriptPass
continue;
}
if (args[argidx] == "-nordff") {
- nordff = true;
+ rdff = false;
continue;
}
if (args[argidx] == "-rdff") {
- nordff = false;
+ rdff = true;
continue;
}
if (args[argidx] == "-nokeepdc") {
@@ -202,7 +202,8 @@ struct PrepPass : public ScriptPass
run(memxmode ? "wreduce -keepdc -memx" : "wreduce -keepdc");
}
if (!nomemmode) {
- run(string("memory_dff") + (help_mode ? " [-nordff]" : nordff ? " -nordff" : ""));
+ if (help_mode || rdff)
+ run("memory_dff", "(if -rdff)");
if (help_mode || memxmode)
run("memory_memx", "(if -memx)");
run("opt_clean");
diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v
index 27ef44232..ad1fdc817 100644
--- a/techlibs/common/simcells.v
+++ b/techlibs/common/simcells.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -1254,6 +1254,290 @@ endmodule
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
+//- $_ALDFF_NN_ (D, C, L, AD, Q)
+//-
+//- A negative edge D-type flip-flop with negative polarity async load.
+//-
+//- Truth table: D C L AD | Q
+//- ----------+---
+//- - - 0 a | a
+//- d \ - - | d
+//- - - - - | q
+//-
+module \$_ALDFF_NN_ (D, C, L, AD, Q);
+input D, C, L, AD;
+output reg Q;
+always @(negedge C or negedge L) begin
+ if (L == 0)
+ Q <= AD;
+ else
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFF_NP_ (D, C, L, AD, Q)
+//-
+//- A negative edge D-type flip-flop with positive polarity async load.
+//-
+//- Truth table: D C L AD | Q
+//- ----------+---
+//- - - 1 a | a
+//- d \ - - | d
+//- - - - - | q
+//-
+module \$_ALDFF_NP_ (D, C, L, AD, Q);
+input D, C, L, AD;
+output reg Q;
+always @(negedge C or posedge L) begin
+ if (L == 1)
+ Q <= AD;
+ else
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFF_PN_ (D, C, L, AD, Q)
+//-
+//- A positive edge D-type flip-flop with negative polarity async load.
+//-
+//- Truth table: D C L AD | Q
+//- ----------+---
+//- - - 0 a | a
+//- d / - - | d
+//- - - - - | q
+//-
+module \$_ALDFF_PN_ (D, C, L, AD, Q);
+input D, C, L, AD;
+output reg Q;
+always @(posedge C or negedge L) begin
+ if (L == 0)
+ Q <= AD;
+ else
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFF_PP_ (D, C, L, AD, Q)
+//-
+//- A positive edge D-type flip-flop with positive polarity async load.
+//-
+//- Truth table: D C L AD | Q
+//- ----------+---
+//- - - 1 a | a
+//- d / - - | d
+//- - - - - | q
+//-
+module \$_ALDFF_PP_ (D, C, L, AD, Q);
+input D, C, L, AD;
+output reg Q;
+always @(posedge C or posedge L) begin
+ if (L == 1)
+ Q <= AD;
+ else
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_NNN_ (D, C, L, AD, E, Q)
+//-
+//- A negative edge D-type flip-flop with negative polarity async load and negative
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 0 a - | a
+//- d \ - - 0 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_NNN_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(negedge C or negedge L) begin
+ if (L == 0)
+ Q <= AD;
+ else if (E == 0)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_NNP_ (D, C, L, AD, E, Q)
+//-
+//- A negative edge D-type flip-flop with negative polarity async load and positive
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 0 a - | a
+//- d \ - - 1 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_NNP_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(negedge C or negedge L) begin
+ if (L == 0)
+ Q <= AD;
+ else if (E == 1)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_NPN_ (D, C, L, AD, E, Q)
+//-
+//- A negative edge D-type flip-flop with positive polarity async load and negative
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 1 a - | a
+//- d \ - - 0 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_NPN_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(negedge C or posedge L) begin
+ if (L == 1)
+ Q <= AD;
+ else if (E == 0)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_NPP_ (D, C, L, AD, E, Q)
+//-
+//- A negative edge D-type flip-flop with positive polarity async load and positive
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 1 a - | a
+//- d \ - - 1 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_NPP_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(negedge C or posedge L) begin
+ if (L == 1)
+ Q <= AD;
+ else if (E == 1)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_PNN_ (D, C, L, AD, E, Q)
+//-
+//- A positive edge D-type flip-flop with negative polarity async load and negative
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 0 a - | a
+//- d / - - 0 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_PNN_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(posedge C or negedge L) begin
+ if (L == 0)
+ Q <= AD;
+ else if (E == 0)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_PNP_ (D, C, L, AD, E, Q)
+//-
+//- A positive edge D-type flip-flop with negative polarity async load and positive
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 0 a - | a
+//- d / - - 1 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_PNP_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(posedge C or negedge L) begin
+ if (L == 0)
+ Q <= AD;
+ else if (E == 1)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_PPN_ (D, C, L, AD, E, Q)
+//-
+//- A positive edge D-type flip-flop with positive polarity async load and negative
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 1 a - | a
+//- d / - - 0 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_PPN_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(posedge C or posedge L) begin
+ if (L == 1)
+ Q <= AD;
+ else if (E == 0)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_PPP_ (D, C, L, AD, E, Q)
+//-
+//- A positive edge D-type flip-flop with positive polarity async load and positive
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 1 a - | a
+//- d / - - 1 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_PPP_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(posedge C or posedge L) begin
+ if (L == 1)
+ Q <= AD;
+ else if (E == 1)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
//- $_DFFSR_NNN_ (C, S, R, D, Q)
//-
//- A negative edge D-type flip-flop with negative polarity set and negative
diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v
index 5c9efad27..b14488ff4 100644
--- a/techlibs/common/simlib.v
+++ b/techlibs/common/simlib.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -1292,6 +1292,33 @@ endmodule
// --------------------------------------------------------
+module \$bmux (A, S, Y);
+
+parameter WIDTH = 0;
+parameter S_WIDTH = 0;
+
+input [(WIDTH << S_WIDTH)-1:0] A;
+input [S_WIDTH-1:0] S;
+output [WIDTH-1:0] Y;
+
+wire [WIDTH-1:0] bm0_out, bm1_out;
+
+generate
+ if (S_WIDTH > 1) begin:muxlogic
+ \$bmux #(.WIDTH(WIDTH), .S_WIDTH(S_WIDTH-1)) bm0 (.A(A), .S(S[S_WIDTH-2:0]), .Y(bm0_out));
+ \$bmux #(.WIDTH(WIDTH), .S_WIDTH(S_WIDTH-1)) bm1 (.A(A[(WIDTH << S_WIDTH)-1:WIDTH << (S_WIDTH - 1)]), .S(S[S_WIDTH-2:0]), .Y(bm1_out));
+ assign Y = S[S_WIDTH-1] ? bm1_out : bm0_out;
+ end else if (S_WIDTH == 1) begin:simple
+ assign Y = S ? A[1] : A[0];
+ end else begin:passthru
+ assign Y = A;
+ end
+endgenerate
+
+endmodule
+
+// --------------------------------------------------------
+
module \$pmux (A, B, S, Y);
parameter WIDTH = 0;
@@ -1318,6 +1345,26 @@ end
endmodule
// --------------------------------------------------------
+
+module \$demux (A, S, Y);
+
+parameter WIDTH = 1;
+parameter S_WIDTH = 1;
+
+input [WIDTH-1:0] A;
+input [S_WIDTH-1:0] S;
+output [(WIDTH << S_WIDTH)-1:0] Y;
+
+genvar i;
+generate
+ for (i = 0; i < (1 << S_WIDTH); i = i + 1) begin:slices
+ assign Y[i*WIDTH+:WIDTH] = (S == i) ? A : 0;
+ end
+endgenerate
+
+endmodule
+
+// --------------------------------------------------------
`ifndef SIMLIB_NOLUT
module \$lut (A, Y);
@@ -1326,30 +1373,9 @@ parameter WIDTH = 0;
parameter LUT = 0;
input [WIDTH-1:0] A;
-output reg Y;
-
-wire lut0_out, lut1_out;
+output Y;
-generate
- if (WIDTH <= 1) begin:simple
- assign {lut1_out, lut0_out} = LUT;
- end else begin:complex
- \$lut #( .WIDTH(WIDTH-1), .LUT(LUT ) ) lut0 ( .A(A[WIDTH-2:0]), .Y(lut0_out) );
- \$lut #( .WIDTH(WIDTH-1), .LUT(LUT >> (2**(WIDTH-1))) ) lut1 ( .A(A[WIDTH-2:0]), .Y(lut1_out) );
- end
-
- if (WIDTH > 0) begin:lutlogic
- always @* begin
- casez ({A[WIDTH-1], lut0_out, lut1_out})
- 3'b?11: Y = 1'b1;
- 3'b?00: Y = 1'b0;
- 3'b0??: Y = lut0_out;
- 3'b1??: Y = lut1_out;
- default: Y = 1'bx;
- endcase
- end
- end
-endgenerate
+\$bmux #(.WIDTH(1), .S_WIDTH(WIDTH)) mux(.A(LUT), .S(A), .Y(Y));
endmodule
@@ -1890,6 +1916,30 @@ endmodule
// --------------------------------------------------------
+module \$aldff (CLK, ALOAD, AD, D, Q);
+
+parameter WIDTH = 0;
+parameter CLK_POLARITY = 1'b1;
+parameter ALOAD_POLARITY = 1'b1;
+
+input CLK, ALOAD;
+input [WIDTH-1:0] AD;
+input [WIDTH-1:0] D;
+output reg [WIDTH-1:0] Q;
+wire pos_clk = CLK == CLK_POLARITY;
+wire pos_aload = ALOAD == ALOAD_POLARITY;
+
+always @(posedge pos_clk, posedge pos_aload) begin
+ if (pos_aload)
+ Q <= AD;
+ else
+ Q <= D;
+end
+
+endmodule
+
+// --------------------------------------------------------
+
module \$sdff (CLK, SRST, D, Q);
parameter WIDTH = 0;
@@ -1939,6 +1989,31 @@ endmodule
// --------------------------------------------------------
+module \$aldffe (CLK, ALOAD, AD, EN, D, Q);
+
+parameter WIDTH = 0;
+parameter CLK_POLARITY = 1'b1;
+parameter EN_POLARITY = 1'b1;
+parameter ALOAD_POLARITY = 1'b1;
+
+input CLK, ALOAD, EN;
+input [WIDTH-1:0] D;
+input [WIDTH-1:0] AD;
+output reg [WIDTH-1:0] Q;
+wire pos_clk = CLK == CLK_POLARITY;
+wire pos_aload = ALOAD == ALOAD_POLARITY;
+
+always @(posedge pos_clk, posedge pos_aload) begin
+ if (pos_aload)
+ Q <= AD;
+ else if (EN == EN_POLARITY)
+ Q <= D;
+end
+
+endmodule
+
+// --------------------------------------------------------
+
module \$sdffe (CLK, SRST, EN, D, Q);
parameter WIDTH = 0;
@@ -2182,6 +2257,34 @@ end
endmodule
+module \$memrd_v2 (CLK, EN, ARST, SRST, ADDR, DATA);
+
+parameter MEMID = "";
+parameter ABITS = 8;
+parameter WIDTH = 8;
+
+parameter CLK_ENABLE = 0;
+parameter CLK_POLARITY = 0;
+parameter TRANSPARENCY_MASK = 0;
+parameter COLLISION_X_MASK = 0;
+parameter ARST_VALUE = 0;
+parameter SRST_VALUE = 0;
+parameter INIT_VALUE = 0;
+parameter CE_OVER_SRST = 0;
+
+input CLK, EN, ARST, SRST;
+input [ABITS-1:0] ADDR;
+output [WIDTH-1:0] DATA;
+
+initial begin
+ if (MEMID != "") begin
+ $display("ERROR: Found non-simulatable instance of $memrd_v2!");
+ $finish;
+ end
+end
+
+endmodule
+
// --------------------------------------------------------
module \$memwr (CLK, EN, ADDR, DATA);
@@ -2208,6 +2311,31 @@ end
endmodule
+module \$memwr_v2 (CLK, EN, ADDR, DATA);
+
+parameter MEMID = "";
+parameter ABITS = 8;
+parameter WIDTH = 8;
+
+parameter CLK_ENABLE = 0;
+parameter CLK_POLARITY = 0;
+parameter PORTID = 0;
+parameter PRIORITY_MASK = 0;
+
+input CLK;
+input [WIDTH-1:0] EN;
+input [ABITS-1:0] ADDR;
+input [WIDTH-1:0] DATA;
+
+initial begin
+ if (MEMID != "") begin
+ $display("ERROR: Found non-simulatable instance of $memwr_v2!");
+ $finish;
+ end
+end
+
+endmodule
+
// --------------------------------------------------------
module \$meminit (ADDR, DATA);
@@ -2233,6 +2361,30 @@ endmodule
// --------------------------------------------------------
+module \$meminit_v2 (ADDR, DATA, EN);
+
+parameter MEMID = "";
+parameter ABITS = 8;
+parameter WIDTH = 8;
+parameter WORDS = 1;
+
+parameter PRIORITY = 0;
+
+input [ABITS-1:0] ADDR;
+input [WORDS*WIDTH-1:0] DATA;
+input [WIDTH-1:0] EN;
+
+initial begin
+ if (MEMID != "") begin
+ $display("ERROR: Found non-simulatable instance of $meminit_v2!");
+ $finish;
+ end
+end
+
+endmodule
+
+// --------------------------------------------------------
+
module \$mem (RD_CLK, RD_EN, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
parameter MEMID = "";
@@ -2320,6 +2472,122 @@ end
endmodule
+module \$mem_v2 (RD_CLK, RD_EN, RD_ARST, RD_SRST, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA);
+
+parameter MEMID = "";
+parameter signed SIZE = 4;
+parameter signed OFFSET = 0;
+parameter signed ABITS = 2;
+parameter signed WIDTH = 8;
+parameter signed INIT = 1'bx;
+
+parameter signed RD_PORTS = 1;
+parameter RD_CLK_ENABLE = 1'b1;
+parameter RD_CLK_POLARITY = 1'b1;
+parameter RD_TRANSPARENCY_MASK = 1'b0;
+parameter RD_COLLISION_X_MASK = 1'b0;
+parameter RD_WIDE_CONTINUATION = 1'b0;
+parameter RD_CE_OVER_SRST = 1'b0;
+parameter RD_ARST_VALUE = 1'b0;
+parameter RD_SRST_VALUE = 1'b0;
+parameter RD_INIT_VALUE = 1'b0;
+
+parameter signed WR_PORTS = 1;
+parameter WR_CLK_ENABLE = 1'b1;
+parameter WR_CLK_POLARITY = 1'b1;
+parameter WR_PRIORITY_MASK = 1'b0;
+parameter WR_WIDE_CONTINUATION = 1'b0;
+
+input [RD_PORTS-1:0] RD_CLK;
+input [RD_PORTS-1:0] RD_EN;
+input [RD_PORTS-1:0] RD_ARST;
+input [RD_PORTS-1:0] RD_SRST;
+input [RD_PORTS*ABITS-1:0] RD_ADDR;
+output reg [RD_PORTS*WIDTH-1:0] RD_DATA;
+
+input [WR_PORTS-1:0] WR_CLK;
+input [WR_PORTS*WIDTH-1:0] WR_EN;
+input [WR_PORTS*ABITS-1:0] WR_ADDR;
+input [WR_PORTS*WIDTH-1:0] WR_DATA;
+
+reg [WIDTH-1:0] memory [SIZE-1:0];
+
+integer i, j, k;
+reg [WR_PORTS-1:0] LAST_WR_CLK;
+reg [RD_PORTS-1:0] LAST_RD_CLK;
+
+function port_active;
+ input clk_enable;
+ input clk_polarity;
+ input last_clk;
+ input this_clk;
+ begin
+ casez ({clk_enable, clk_polarity, last_clk, this_clk})
+ 4'b0???: port_active = 1;
+ 4'b1101: port_active = 1;
+ 4'b1010: port_active = 1;
+ default: port_active = 0;
+ endcase
+ end
+endfunction
+
+initial begin
+ for (i = 0; i < SIZE; i = i+1)
+ memory[i] = INIT >>> (i*WIDTH);
+ RD_DATA = RD_INIT_VALUE;
+end
+
+always @(RD_CLK, RD_ARST, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA) begin
+`ifdef SIMLIB_MEMDELAY
+ #`SIMLIB_MEMDELAY;
+`endif
+ for (i = 0; i < RD_PORTS; i = i+1) begin
+ if (RD_CLK_ENABLE[i] && RD_EN[i] && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i])) begin
+ // $display("Read from %s: addr=%b data=%b", MEMID, RD_ADDR[i*ABITS +: ABITS], memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]);
+ RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET];
+
+ for (j = 0; j < WR_PORTS; j = j+1) begin
+ if (RD_TRANSPARENCY_MASK[i*WR_PORTS + j] && port_active(WR_CLK_ENABLE[j], WR_CLK_POLARITY[j], LAST_WR_CLK[j], WR_CLK[j]) && RD_ADDR[i*ABITS +: ABITS] == WR_ADDR[j*ABITS +: ABITS])
+ for (k = 0; k < WIDTH; k = k+1)
+ if (WR_EN[j*WIDTH+k])
+ RD_DATA[i*WIDTH+k] <= WR_DATA[j*WIDTH+k];
+ if (RD_COLLISION_X_MASK[i*WR_PORTS + j] && port_active(WR_CLK_ENABLE[j], WR_CLK_POLARITY[j], LAST_WR_CLK[j], WR_CLK[j]) && RD_ADDR[i*ABITS +: ABITS] == WR_ADDR[j*ABITS +: ABITS])
+ for (k = 0; k < WIDTH; k = k+1)
+ if (WR_EN[j*WIDTH+k])
+ RD_DATA[i*WIDTH+k] <= 1'bx;
+ end
+ end
+ end
+
+ for (i = 0; i < WR_PORTS; i = i+1) begin
+ if (port_active(WR_CLK_ENABLE[i], WR_CLK_POLARITY[i], LAST_WR_CLK[i], WR_CLK[i]))
+ for (j = 0; j < WIDTH; j = j+1)
+ if (WR_EN[i*WIDTH+j]) begin
+ // $display("Write to %s: addr=%b data=%b", MEMID, WR_ADDR[i*ABITS +: ABITS], WR_DATA[i*WIDTH+j]);
+ memory[WR_ADDR[i*ABITS +: ABITS] - OFFSET][j] = WR_DATA[i*WIDTH+j];
+ end
+ end
+
+ for (i = 0; i < RD_PORTS; i = i+1) begin
+ if (!RD_CLK_ENABLE[i]) begin
+ // $display("Combinatorial read from %s: addr=%b data=%b", MEMID, RD_ADDR[i*ABITS +: ABITS], memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET]);
+ RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET];
+ end
+ end
+
+ for (i = 0; i < RD_PORTS; i = i+1) begin
+ if (RD_SRST[i] && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i]) && (RD_EN[i] || !RD_CE_OVER_SRST[i]))
+ RD_DATA[i*WIDTH +: WIDTH] <= RD_SRST_VALUE[i*WIDTH +: WIDTH];
+ if (RD_ARST[i])
+ RD_DATA[i*WIDTH +: WIDTH] <= RD_ARST_VALUE[i*WIDTH +: WIDTH];
+ end
+
+ LAST_RD_CLK <= RD_CLK;
+ LAST_WR_CLK <= WR_CLK;
+end
+
+endmodule
+
`endif
// --------------------------------------------------------
diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc
index 89d6e530e..79e5933e0 100644
--- a/techlibs/common/synth.cc
+++ b/techlibs/common/synth.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v
index 2ab28e6e6..91d385b80 100644
--- a/techlibs/common/techmap.v
+++ b/techlibs/common/techmap.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -59,12 +59,12 @@ module _90_simplemap_compare_ops;
endmodule
(* techmap_simplemap *)
-(* techmap_celltype = "$pos $slice $concat $mux $tribuf" *)
+(* techmap_celltype = "$pos $slice $concat $mux $tribuf $bmux" *)
module _90_simplemap_various;
endmodule
(* techmap_simplemap *)
-(* techmap_celltype = "$sr $ff $dff $dffe $adff $adffe $sdff $sdffe $sdffce $dffsr $dffsre $dlatch $adlatch $dlatchsr" *)
+(* techmap_celltype = "$sr $ff $dff $dffe $adff $adffe $aldff $aldffe $sdff $sdffe $sdffce $dffsr $dffsre $dlatch $adlatch $dlatchsr" *)
module _90_simplemap_registers;
endmodule
@@ -597,6 +597,43 @@ module _90_pmux (A, B, S, Y);
assign Y = |S ? Y_B : A;
endmodule
+// --------------------------------------------------------
+// Demultiplexers
+// --------------------------------------------------------
+
+(* techmap_celltype = "$demux" *)
+module _90_demux (A, S, Y);
+ parameter WIDTH = 1;
+ parameter S_WIDTH = 1;
+
+ (* force_downto *)
+ input [WIDTH-1:0] A;
+ (* force_downto *)
+ input [S_WIDTH-1:0] S;
+ (* force_downto *)
+ output [(WIDTH << S_WIDTH)-1:0] Y;
+
+ generate
+ if (S_WIDTH == 0) begin
+ assign Y = A;
+ end else if (S_WIDTH == 1) begin
+ assign Y[0+:WIDTH] = S ? 0 : A;
+ assign Y[WIDTH+:WIDTH] = S ? A : 0;
+ end else begin
+ localparam SPLIT = S_WIDTH / 2;
+ wire [(1 << (S_WIDTH-SPLIT))-1:0] YH;
+ wire [(1 << SPLIT)-1:0] YL;
+ $demux #(.WIDTH(1), .S_WIDTH(SPLIT)) lo (.A(1'b1), .S(S[SPLIT-1:0]), .Y(YL));
+ $demux #(.WIDTH(1), .S_WIDTH(S_WIDTH-SPLIT)) hi (.A(1'b1), .S(S[S_WIDTH-1:SPLIT]), .Y(YH));
+ genvar i;
+ for (i = 0; i < (1 << S_WIDTH); i = i + 1) begin
+ localparam [S_WIDTH-1:0] IDX = i;
+ assign Y[i*WIDTH+:WIDTH] = (YL[IDX[SPLIT-1:0]] & YH[IDX[S_WIDTH-1:SPLIT]]) ? A : 0;
+ end
+ end
+ endgenerate
+endmodule
+
// --------------------------------------------------------
// LUTs
diff --git a/techlibs/coolrunner2/synth_coolrunner2.cc b/techlibs/coolrunner2/synth_coolrunner2.cc
index 47102fbb1..a746ac222 100644
--- a/techlibs/coolrunner2/synth_coolrunner2.cc
+++ b/techlibs/coolrunner2/synth_coolrunner2.cc
@@ -192,6 +192,7 @@ struct SynthCoolrunner2Pass : public ScriptPass
run("hierarchy -check");
run("stat");
run("check -noinit");
+ run("blackbox =A:whitebox");
}
if (check_label("json"))
diff --git a/techlibs/easic/synth_easic.cc b/techlibs/easic/synth_easic.cc
index 897bc1c40..50526a9ea 100644
--- a/techlibs/easic/synth_easic.cc
+++ b/techlibs/easic/synth_easic.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -175,6 +175,7 @@ struct SynthEasicPass : public ScriptPass
run("hierarchy -check");
run("stat");
run("check -noinit");
+ run("blackbox =A:whitebox");
}
if (check_label("vlog"))
diff --git a/techlibs/ecp5/arith_map.v b/techlibs/ecp5/arith_map.v
index ffd42469c..9334785ae 100644
--- a/techlibs/ecp5/arith_map.v
+++ b/techlibs/ecp5/arith_map.v
@@ -1,8 +1,8 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * Copyright (C) 2018 David Shah <dave@ds0.me>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
+ * Copyright (C) 2018 gatecat <gatecat@ds0.me>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
diff --git a/techlibs/ecp5/brams.txt b/techlibs/ecp5/brams.txt
index d34d9ec07..615d8b2e5 100644
--- a/techlibs/ecp5/brams.txt
+++ b/techlibs/ecp5/brams.txt
@@ -38,7 +38,7 @@ bram $__ECP5_DP16KD
endbram
# The syn_* attributes are described in:
-# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx
+# https://www.latticesemi.com/view_document?document_id=51556
attr_icase 1
match $__ECP5_PDPW16KD
diff --git a/techlibs/ecp5/cells_bb.v b/techlibs/ecp5/cells_bb.v
index 756f05366..e616d24d6 100644
--- a/techlibs/ecp5/cells_bb.v
+++ b/techlibs/ecp5/cells_bb.v
@@ -27,16 +27,23 @@ module MULT18X18D(
parameter REG_INPUTB_CE = "CE0";
parameter REG_INPUTB_RST = "RST0";
parameter REG_INPUTC_CLK = "NONE";
+ parameter REG_INPUTC_CE = "CE0";
+ parameter REG_INPUTC_RST = "RST0";
parameter REG_PIPELINE_CLK = "NONE";
parameter REG_PIPELINE_CE = "CE0";
parameter REG_PIPELINE_RST = "RST0";
parameter REG_OUTPUT_CLK = "NONE";
+ parameter REG_OUTPUT_CE = "CE0";
+ parameter REG_OUTPUT_RST = "RST0";
parameter [127:0] CLK0_DIV = "ENABLED";
parameter [127:0] CLK1_DIV = "ENABLED";
parameter [127:0] CLK2_DIV = "ENABLED";
parameter [127:0] CLK3_DIV = "ENABLED";
+ parameter HIGHSPEED_CLK = "NONE";
parameter [127:0] GSR = "ENABLED";
+ parameter CAS_MATCH_REG = "FALSE";
parameter [127:0] SOURCEB_MODE = "B_SHIFT";
+ parameter [127:0] MULT_BYPASS = "DISABLED";
parameter [127:0] RESETMODE = "SYNC";
endmodule
@@ -61,7 +68,11 @@ module ALU54B(
output SIGNEDR
);
parameter REG_INPUTC0_CLK = "NONE";
+ parameter REG_INPUTC0_CE = "CE0";
+ parameter REG_INPUTC0_RST = "RST0";
parameter REG_INPUTC1_CLK = "NONE";
+ parameter REG_INPUTC1_CE = "CE0";
+ parameter REG_INPUTC1_RST = "RST0";
parameter REG_OPCODEOP0_0_CLK = "NONE";
parameter REG_OPCODEOP0_0_CE = "CE0";
parameter REG_OPCODEOP0_0_RST = "RST0";
@@ -69,6 +80,7 @@ module ALU54B(
parameter REG_OPCODEOP0_1_CLK = "NONE";
parameter REG_OPCODEOP0_1_CE = "CE0";
parameter REG_OPCODEOP0_1_RST = "RST0";
+ parameter REG_OPCODEOP1_1_CLK = "NONE";
parameter REG_OPCODEIN_0_CLK = "NONE";
parameter REG_OPCODEIN_0_CE = "CE0";
parameter REG_OPCODEIN_0_RST = "RST0";
@@ -76,8 +88,17 @@ module ALU54B(
parameter REG_OPCODEIN_1_CE = "CE0";
parameter REG_OPCODEIN_1_RST = "RST0";
parameter REG_OUTPUT0_CLK = "NONE";
+ parameter REG_OUTPUT0_CE = "CE0";
+ parameter REG_OUTPUT0_RST = "RST0";
parameter REG_OUTPUT1_CLK = "NONE";
+ parameter REG_OUTPUT1_CE = "CE0";
+ parameter REG_OUTPUT1_RST = "RST0";
parameter REG_FLAG_CLK = "NONE";
+ parameter REG_FLAG_CE = "CE0";
+ parameter REG_FLAG_RST = "RST0";
+ parameter REG_INPUTCFB_CLK = "NONE";
+ parameter REG_INPUTCFB_CE = "CE0";
+ parameter REG_INPUTCFB_RST = "RST0";
parameter [127:0] MCPAT_SOURCE = "STATIC";
parameter [127:0] MASKPAT_SOURCE = "STATIC";
parameter MASK01 = "0x00000000000000";
@@ -90,6 +111,7 @@ module ALU54B(
parameter RNDPAT = "0x00000000000000";
parameter [127:0] GSR = "ENABLED";
parameter [127:0] RESETMODE = "SYNC";
+ parameter MULT9_MODE = "DISABLED";
parameter FORCE_ZERO_BARREL_SHIFT = "DISABLED";
parameter LEGACY = "DISABLED";
endmodule
@@ -318,6 +340,15 @@ module DDRDLLA(
endmodule
(* blackbox *)
+module DLLDELD(
+ input A, DDRDEL, LOADN, MOVE, DIRECTION,
+ output Z, CFLAG
+);
+ parameter DEL_ADJ = "PLUS";
+ parameter DEL_VAL = 0;
+endmodule
+
+(* blackbox *)
module CLKDIVF(
input CLKI, RST, ALIGNWD,
output CDIVX
@@ -347,6 +378,16 @@ module DCCA(
);
endmodule
+(* blackbox *)
+module DCSC(
+ input CLK1, CLK0,
+ input SEL1, SEL0,
+ input MODESEL,
+ output DCSOUT
+);
+ parameter DCSMODE = "POS";
+endmodule
+
(* blackbox *) (* keep *)
module DCUA(
input CH0_HDINP, CH1_HDINP, CH0_HDINN, CH1_HDINN,
diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v
index dc83d96dc..4944ece45 100644
--- a/techlibs/ecp5/cells_map.v
+++ b/techlibs/ecp5/cells_map.v
@@ -88,14 +88,13 @@ module \$_SDFFE_NP1N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"),
module \$_SDFFE_PP0N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
module \$_SDFFE_PP1N_ (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("AUTO"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; endmodule
-`ifdef ASYNC_PRLD
-module \$_DLATCH_N_ (input E, input D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.LSR(!E), .DI(1'b0), .M(D), .Q(Q)); endmodule
-module \$_DLATCH_P_ (input E, input D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.LSR(E), .DI(1'b0), .M(D), .Q(Q)); endmodule
+module \$_ALDFF_NP_ (input C, L, AD, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(L), .DI(D), .M(AD), .Q(Q)); endmodule
+module \$_ALDFF_PP_ (input C, L, AD, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(L), .DI(D), .M(AD), .Q(Q)); endmodule
-module \$_DFFSR_NPP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || R), .DI(D), .M(!R), .Q(Q)); endmodule
-
-module \$_DFFSR_PPP_ (input C, S, R, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(S || R), .DI(D), .M(!R), .Q(Q)); endmodule
-`endif
+module \$_ALDFFE_NPN_ (input C, E, L, AD, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("INV"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(L), .DI(D), .M(AD), .Q(Q)); endmodule
+module \$_ALDFFE_NPP_ (input C, E, L, AD, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(L), .DI(D), .M(AD), .Q(Q)); endmodule
+module \$_ALDFFE_PPN_ (input C, E, L, AD, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("INV"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(L), .DI(D), .M(AD), .Q(Q)); endmodule
+module \$_ALDFFE_PPP_ (input C, E, L, AD, D, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMODE("PRLD"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(L), .DI(D), .M(AD), .Q(Q)); endmodule
`include "cells_ff.vh"
`include "cells_io.vh"
diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v
index 357fd9173..a5f905cf8 100644
--- a/techlibs/ecp5/cells_sim.v
+++ b/techlibs/ecp5/cells_sim.v
@@ -204,7 +204,7 @@ module TRELLIS_DPR16X4 (
integer i;
initial begin
for (i = 0; i < 16; i = i + 1)
- mem[i] <= {INITVAL[i+3], INITVAL[i+2], INITVAL[i+1], INITVAL[i]};
+ mem[i] <= INITVAL[4*i +: 4];
end
wire muxwck = (WCKMUX == "INV") ? ~WCK : WCK;
diff --git a/techlibs/ecp5/ecp5_gsr.cc b/techlibs/ecp5/ecp5_gsr.cc
index 18d99cfb2..62b231aab 100644
--- a/techlibs/ecp5/ecp5_gsr.cc
+++ b/techlibs/ecp5/ecp5_gsr.cc
@@ -1,8 +1,8 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * Copyright (C) 2019 David Shah <david@symbioticeda.com>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
+ * Copyright (C) 2019 gatecat <gatecat@ds0.me>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
diff --git a/techlibs/ecp5/lutrams.txt b/techlibs/ecp5/lutrams.txt
index 9e6a23eba..5370a1ddb 100644
--- a/techlibs/ecp5/lutrams.txt
+++ b/techlibs/ecp5/lutrams.txt
@@ -12,7 +12,7 @@ bram $__TRELLIS_DPR16X4
endbram
# The syn_* attributes are described in:
-# https://www.latticesemi.com/-/media/LatticeSemi/Documents/Tutorials/AK/LatticeDiamondTutorial311.ashx
+# https://www.latticesemi.com/view_document?document_id=51556
attr_icase 1
match $__TRELLIS_DPR16X4
diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc
index 3cee9722e..eb8ba8b9d 100644
--- a/techlibs/ecp5/synth_ecp5.cc
+++ b/techlibs/ecp5/synth_ecp5.cc
@@ -1,8 +1,8 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * Copyright (C) 2018 David Shah <dave@ds0.me>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
+ * Copyright (C) 2018 gatecat <gatecat@ds0.me>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -88,7 +88,7 @@ struct SynthEcp5Pass : public ScriptPass
log(" do not use PFU muxes to implement LUTs larger than LUT4s\n");
log("\n");
log(" -asyncprld\n");
- log(" use async PRLD mode to implement DLATCH and DFFSR (EXPERIMENTAL)\n");
+ log(" use async PRLD mode to implement ALDFF (EXPERIMENTAL)\n");
log("\n");
log(" -abc2\n");
log(" run two passes of 'abc' for slightly improved logic density\n");
@@ -318,16 +318,17 @@ struct SynthEcp5Pass : public ScriptPass
} else if (!nodffe) {
dfflegalize_args += " -cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r";
}
- dfflegalize_args += " -cell $_DLATCH_?_ x";
if (help_mode) {
- dfflegalize_args += " [-cell $_DFFSR_?PP_ x]";
+ dfflegalize_args += " [-cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x] [-cell $_DLATCH_?_ x]";
} else if (asyncprld) {
- dfflegalize_args += " -cell $_DFFSR_?PP_ x";
+ dfflegalize_args += " -cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x";
+ } else {
+ dfflegalize_args += " -cell $_DLATCH_?_ x";
}
- run("dfflegalize" + dfflegalize_args, "($_DFFSR_*_ only if -asyncprld, $_*DFFE_* only if not -nodffe)");
+ run("dfflegalize" + dfflegalize_args, "($_ALDFF_*_ only if -asyncprld, $_DLATCH_* only if not -asyncprld, $_*DFFE_* only if not -nodffe)");
if ((abc9 && dff) || help_mode)
- run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF*", "(only if -abc9 and -dff");
- run(stringf("techmap -D NO_LUT %s -map +/ecp5/cells_map.v", help_mode ? "[-D ASYNC_PRLD]" : (asyncprld ? "-D ASYNC_PRLD" : "")));
+ run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF*", "(only if -abc9 and -dff)");
+ run("techmap -D NO_LUT -map +/ecp5/cells_map.v");
run("opt_expr -undriven -mux_undef");
run("simplemap");
run("ecp5_gsr");
@@ -385,6 +386,7 @@ struct SynthEcp5Pass : public ScriptPass
run("hierarchy -check");
run("stat");
run("check -noinit");
+ run("blackbox =A:whitebox");
}
if (check_label("blif"))
diff --git a/techlibs/efinix/arith_map.v b/techlibs/efinix/arith_map.v
index 4dac360b9..6bda0505c 100644
--- a/techlibs/efinix/arith_map.v
+++ b/techlibs/efinix/arith_map.v
@@ -1,8 +1,8 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 Miodrag Milanovic <micko@yosyshq.com>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/efinix/efinix_fixcarry.cc b/techlibs/efinix/efinix_fixcarry.cc
index 486b8e89c..c61fa79b8 100644
--- a/techlibs/efinix/efinix_fixcarry.cc
+++ b/techlibs/efinix/efinix_fixcarry.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
+ * Copyright (C) 2019 Miodrag Milanovic <micko@yosyshq.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
diff --git a/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc
index 001b05945..ace56bee9 100644
--- a/techlibs/efinix/synth_efinix.cc
+++ b/techlibs/efinix/synth_efinix.cc
@@ -1,8 +1,8 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2019 Miodrag Milanovic <miodrag@symbioticeda.com>
- * Copyright (C) 2019 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2019 Miodrag Milanovic <micko@yosyshq.com>
+ * Copyright (C) 2019 Claire Xenia Wolf <claire@yosyshq.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
@@ -213,6 +213,7 @@ struct SynthEfinixPass : public ScriptPass
run("hierarchy -check");
run("stat");
run("check -noinit");
+ run("blackbox =A:whitebox");
}
if (check_label("edif"))
diff --git a/techlibs/gatemate/Makefile.inc b/techlibs/gatemate/Makefile.inc
new file mode 100644
index 000000000..d1341d7bb
--- /dev/null
+++ b/techlibs/gatemate/Makefile.inc
@@ -0,0 +1,14 @@
+
+OBJS += techlibs/gatemate/synth_gatemate.o
+
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/reg_map.v))
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/mux_map.v))
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/lut_map.v))
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/mul_map.v))
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/arith_map.v))
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/cells_sim.v))
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/cells_bb.v))
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams_map.v))
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams.txt))
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams_init_20.vh))
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams_init_40.vh))
diff --git a/techlibs/gatemate/arith_map.v b/techlibs/gatemate/arith_map.v
new file mode 100644
index 000000000..a3ab9c186
--- /dev/null
+++ b/techlibs/gatemate/arith_map.v
@@ -0,0 +1,69 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Cologne Chip AG <support@colognechip.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.
+ *
+ */
+
+(* techmap_celltype = "$alu" *)
+module _80_gatemate_alu(A, B, CI, BI, X, Y, CO);
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+ parameter A_WIDTH = 1;
+ parameter B_WIDTH = 1;
+ parameter Y_WIDTH = 1;
+
+ (* force_downto *)
+ input [A_WIDTH-1:0] A;
+ (* force_downto *)
+ input [B_WIDTH-1:0] B;
+ (* force_downto *)
+ output [Y_WIDTH-1:0] X, Y;
+
+ input CI, BI;
+ (* force_downto *)
+ output [Y_WIDTH-1:0] CO;
+
+ wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;
+
+ (* force_downto *)
+ wire [Y_WIDTH-1:0] A_buf, B_buf;
+ \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
+ \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));
+
+ (* force_downto *)
+ wire [Y_WIDTH-1:0] AA = A_buf;
+ (* force_downto *)
+ wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
+ (* force_downto *)
+ wire [Y_WIDTH-1:0] C = {CO, CI};
+
+ genvar i;
+ generate
+ for (i = 0; i < Y_WIDTH; i = i + 1)
+ begin: slice
+ CC_ADDF addf_i (
+ .A(AA[i]),
+ .B(BB[i]),
+ .CI(C[i]),
+ .CO(CO[i]),
+ .S(Y[i])
+ );
+ end
+ endgenerate
+
+ assign X = AA ^ BB;
+
+endmodule
diff --git a/techlibs/gatemate/brams.txt b/techlibs/gatemate/brams.txt
new file mode 100644
index 000000000..9e0bebba6
--- /dev/null
+++ b/techlibs/gatemate/brams.txt
@@ -0,0 +1,280 @@
+bram $__CC_BRAM_CASCADE
+ init 1
+ abits 16 @a16d1
+ dbits 1 @a16d1
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ enable 1 1 @a16d1
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+bram $__CC_BRAM_40K_SDP
+ init 1
+ abits 9 @a9d80
+ dbits 80 @a9d80
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ enable 80 1 @a9d80
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+bram $__CC_BRAM_20K_SDP
+ init 1
+ abits 9 @a9d40
+ dbits 40 @a9d40
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ enable 40 1 @a9d40
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+bram $__CC_BRAM_40K_TDP
+ init 1
+ abits 10 @a10d40
+ dbits 40 @a10d40
+ abits 11 @a11d20
+ dbits 20 @a11d20
+ abits 12 @a12d10
+ dbits 10 @a12d10
+ abits 13 @a13d5
+ dbits 5 @a13d5
+ abits 14 @a14d2
+ dbits 2 @a14d2
+ abits 15 @a15d1
+ dbits 1 @a15d1
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ enable 40 1 @a10d40
+ enable 20 1 @a11d20
+ enable 10 1 @a12d10
+ enable 5 1 @a13d5
+ enable 2 1 @a14d2
+ enable 1 1 @a15d1
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+bram $__CC_BRAM_20K_TDP
+ init 1
+ abits 10 @a10d20
+ dbits 20 @a10d20
+ abits 11 @a11d10
+ dbits 10 @a11d10
+ abits 12 @a12d5
+ dbits 5 @a12d5
+ abits 13 @a13d2
+ dbits 2 @a13d2
+ abits 14 @a14d1
+ dbits 1 @a14d1
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ enable 20 1 @a10d20
+ enable 10 1 @a11d10
+ enable 5 1 @a12d5
+ enable 2 1 @a13d2
+ enable 1 1 @a14d1
+ transp 0 0
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+match $__CC_BRAM_CASCADE
+ # implicitly requested RAM or ROM
+ attribute !syn_ramstyle syn_ramstyle=auto
+ attribute !syn_romstyle syn_romstyle=auto
+ attribute !ram_block
+ attribute !rom_block
+ attribute !logic_block
+ min bits 512
+ min efficiency 5
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__CC_BRAM_CASCADE
+ # explicitly requested RAM
+ attribute syn_ramstyle=block_ram ram_block
+ attribute !syn_romstyle
+ attribute !rom_block
+ attribute !logic_block
+ min wports 1
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__CC_BRAM_CASCADE
+ # explicitly requested ROM
+ attribute syn_romstyle=ebr rom_block
+ attribute !syn_ramstyle
+ attribute !ram_block
+ attribute !logic_block
+ max wports 0
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__CC_BRAM_40K_SDP
+ # implicitly requested RAM or ROM
+ attribute !syn_ramstyle syn_ramstyle=auto
+ attribute !syn_romstyle syn_romstyle=auto
+ attribute !ram_block
+ attribute !rom_block
+ attribute !logic_block
+ min bits 512
+ min efficiency 5
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__CC_BRAM_40K_SDP
+ # explicitly requested RAM
+ attribute syn_ramstyle=block_ram ram_block
+ attribute !syn_romstyle
+ attribute !rom_block
+ attribute !logic_block
+ min wports 1
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__CC_BRAM_40K_SDP
+ # explicitly requested ROM
+ attribute syn_romstyle=ebr rom_block
+ attribute !syn_ramstyle
+ attribute !ram_block
+ attribute !logic_block
+ max wports 0
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__CC_BRAM_20K_SDP
+ # implicitly requested RAM or ROM
+ attribute !syn_ramstyle syn_ramstyle=auto
+ attribute !syn_romstyle syn_romstyle=auto
+ attribute !ram_block
+ attribute !rom_block
+ attribute !logic_block
+ min bits 512
+ min efficiency 5
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__CC_BRAM_20K_SDP
+ # explicitly requested RAM
+ attribute syn_ramstyle=block_ram ram_block
+ attribute !syn_romstyle
+ attribute !rom_block
+ attribute !logic_block
+ min wports 1
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__CC_BRAM_20K_SDP
+ # explicitly requested ROM
+ attribute syn_romstyle=ebr rom_block
+ attribute !syn_ramstyle
+ attribute !ram_block
+ attribute !logic_block
+ max wports 0
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__CC_BRAM_40K_TDP
+ # implicitly requested RAM or ROM
+ attribute !syn_ramstyle syn_ramstyle=auto
+ attribute !syn_romstyle syn_romstyle=auto
+ attribute !ram_block
+ attribute !rom_block
+ attribute !logic_block
+ min bits 512
+ min efficiency 5
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__CC_BRAM_40K_TDP
+ # explicitly requested RAM
+ attribute syn_ramstyle=block_ram ram_block
+ attribute !syn_romstyle
+ attribute !rom_block
+ attribute !logic_block
+ min wports 1
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__CC_BRAM_40K_TDP
+ # explicitly requested ROM
+ attribute syn_romstyle=ebr rom_block
+ attribute !syn_ramstyle
+ attribute !ram_block
+ attribute !logic_block
+ max wports 0
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__CC_BRAM_20K_TDP
+ # implicitly requested RAM or ROM
+ attribute !syn_ramstyle syn_ramstyle=auto
+ attribute !syn_romstyle syn_romstyle=auto
+ attribute !ram_block
+ attribute !rom_block
+ attribute !logic_block
+ min bits 512
+ min efficiency 5
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__CC_BRAM_20K_TDP
+ # explicitly requested RAM
+ attribute syn_ramstyle=block_ram ram_block
+ attribute !syn_romstyle
+ attribute !rom_block
+ attribute !logic_block
+ min wports 1
+ shuffle_enable A
+ make_transp
+ or_next_if_better
+endmatch
+
+match $__CC_BRAM_20K_TDP
+ # explicitly requested ROM
+ attribute syn_romstyle=ebr rom_block
+ attribute !syn_ramstyle
+ attribute !ram_block
+ attribute !logic_block
+ max wports 0
+ shuffle_enable A
+ make_transp
+endmatch
diff --git a/techlibs/gatemate/brams_init_20.vh b/techlibs/gatemate/brams_init_20.vh
new file mode 100644
index 000000000..d0764ed2a
--- /dev/null
+++ b/techlibs/gatemate/brams_init_20.vh
@@ -0,0 +1,64 @@
+.INIT_00(permute_init(INIT[ 0*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_01(permute_init(INIT[ 1*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_02(permute_init(INIT[ 2*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_03(permute_init(INIT[ 3*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_04(permute_init(INIT[ 4*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_05(permute_init(INIT[ 5*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_06(permute_init(INIT[ 6*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_07(permute_init(INIT[ 7*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_08(permute_init(INIT[ 8*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_09(permute_init(INIT[ 9*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0A(permute_init(INIT[ 10*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0B(permute_init(INIT[ 11*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0C(permute_init(INIT[ 12*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0D(permute_init(INIT[ 13*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0E(permute_init(INIT[ 14*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0F(permute_init(INIT[ 15*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_10(permute_init(INIT[ 16*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_11(permute_init(INIT[ 17*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_12(permute_init(INIT[ 18*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_13(permute_init(INIT[ 19*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_14(permute_init(INIT[ 20*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_15(permute_init(INIT[ 21*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_16(permute_init(INIT[ 22*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_17(permute_init(INIT[ 23*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_18(permute_init(INIT[ 24*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_19(permute_init(INIT[ 25*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1A(permute_init(INIT[ 26*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1B(permute_init(INIT[ 27*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1C(permute_init(INIT[ 28*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1D(permute_init(INIT[ 29*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1E(permute_init(INIT[ 30*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1F(permute_init(INIT[ 31*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_20(permute_init(INIT[ 32*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_21(permute_init(INIT[ 33*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_22(permute_init(INIT[ 34*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_23(permute_init(INIT[ 35*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_24(permute_init(INIT[ 36*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_25(permute_init(INIT[ 37*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_26(permute_init(INIT[ 38*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_27(permute_init(INIT[ 39*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_28(permute_init(INIT[ 40*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_29(permute_init(INIT[ 41*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2A(permute_init(INIT[ 42*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2B(permute_init(INIT[ 43*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2C(permute_init(INIT[ 44*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2D(permute_init(INIT[ 45*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2E(permute_init(INIT[ 46*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2F(permute_init(INIT[ 47*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_30(permute_init(INIT[ 48*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_31(permute_init(INIT[ 49*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_32(permute_init(INIT[ 50*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_33(permute_init(INIT[ 51*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_34(permute_init(INIT[ 52*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_35(permute_init(INIT[ 53*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_36(permute_init(INIT[ 54*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_37(permute_init(INIT[ 55*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_38(permute_init(INIT[ 56*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_39(permute_init(INIT[ 57*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3A(permute_init(INIT[ 58*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3B(permute_init(INIT[ 59*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3C(permute_init(INIT[ 60*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3D(permute_init(INIT[ 61*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3E(permute_init(INIT[ 62*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3F(permute_init(INIT[ 63*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
diff --git a/techlibs/gatemate/brams_init_40.vh b/techlibs/gatemate/brams_init_40.vh
new file mode 100644
index 000000000..649342560
--- /dev/null
+++ b/techlibs/gatemate/brams_init_40.vh
@@ -0,0 +1,260 @@
+`ifdef INIT_LOWER
+.INIT_00(permute_init(INIT[ 0*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_01(permute_init(INIT[ 1*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_02(permute_init(INIT[ 2*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_03(permute_init(INIT[ 3*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_04(permute_init(INIT[ 4*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_05(permute_init(INIT[ 5*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_06(permute_init(INIT[ 6*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_07(permute_init(INIT[ 7*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_08(permute_init(INIT[ 8*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_09(permute_init(INIT[ 9*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0A(permute_init(INIT[ 10*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0B(permute_init(INIT[ 11*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0C(permute_init(INIT[ 12*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0D(permute_init(INIT[ 13*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0E(permute_init(INIT[ 14*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0F(permute_init(INIT[ 15*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_10(permute_init(INIT[ 16*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_11(permute_init(INIT[ 17*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_12(permute_init(INIT[ 18*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_13(permute_init(INIT[ 19*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_14(permute_init(INIT[ 20*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_15(permute_init(INIT[ 21*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_16(permute_init(INIT[ 22*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_17(permute_init(INIT[ 23*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_18(permute_init(INIT[ 24*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_19(permute_init(INIT[ 25*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1A(permute_init(INIT[ 26*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1B(permute_init(INIT[ 27*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1C(permute_init(INIT[ 28*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1D(permute_init(INIT[ 29*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1E(permute_init(INIT[ 30*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1F(permute_init(INIT[ 31*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_20(permute_init(INIT[ 32*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_21(permute_init(INIT[ 33*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_22(permute_init(INIT[ 34*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_23(permute_init(INIT[ 35*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_24(permute_init(INIT[ 36*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_25(permute_init(INIT[ 37*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_26(permute_init(INIT[ 38*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_27(permute_init(INIT[ 39*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_28(permute_init(INIT[ 40*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_29(permute_init(INIT[ 41*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2A(permute_init(INIT[ 42*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2B(permute_init(INIT[ 43*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2C(permute_init(INIT[ 44*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2D(permute_init(INIT[ 45*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2E(permute_init(INIT[ 46*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2F(permute_init(INIT[ 47*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_30(permute_init(INIT[ 48*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_31(permute_init(INIT[ 49*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_32(permute_init(INIT[ 50*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_33(permute_init(INIT[ 51*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_34(permute_init(INIT[ 52*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_35(permute_init(INIT[ 53*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_36(permute_init(INIT[ 54*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_37(permute_init(INIT[ 55*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_38(permute_init(INIT[ 56*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_39(permute_init(INIT[ 57*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3A(permute_init(INIT[ 58*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3B(permute_init(INIT[ 59*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3C(permute_init(INIT[ 60*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3D(permute_init(INIT[ 61*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3E(permute_init(INIT[ 62*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3F(permute_init(INIT[ 63*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_40(permute_init(INIT[ 64*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_41(permute_init(INIT[ 65*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_42(permute_init(INIT[ 66*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_43(permute_init(INIT[ 67*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_44(permute_init(INIT[ 68*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_45(permute_init(INIT[ 69*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_46(permute_init(INIT[ 70*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_47(permute_init(INIT[ 71*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_48(permute_init(INIT[ 72*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_49(permute_init(INIT[ 73*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4A(permute_init(INIT[ 74*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4B(permute_init(INIT[ 75*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4C(permute_init(INIT[ 76*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4D(permute_init(INIT[ 77*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4E(permute_init(INIT[ 78*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4F(permute_init(INIT[ 79*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_50(permute_init(INIT[ 80*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_51(permute_init(INIT[ 81*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_52(permute_init(INIT[ 82*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_53(permute_init(INIT[ 83*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_54(permute_init(INIT[ 84*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_55(permute_init(INIT[ 85*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_56(permute_init(INIT[ 86*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_57(permute_init(INIT[ 87*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_58(permute_init(INIT[ 88*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_59(permute_init(INIT[ 89*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5A(permute_init(INIT[ 90*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5B(permute_init(INIT[ 91*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5C(permute_init(INIT[ 92*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5D(permute_init(INIT[ 93*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5E(permute_init(INIT[ 94*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5F(permute_init(INIT[ 95*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_60(permute_init(INIT[ 96*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_61(permute_init(INIT[ 97*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_62(permute_init(INIT[ 98*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_63(permute_init(INIT[ 99*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_64(permute_init(INIT[100*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_65(permute_init(INIT[101*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_66(permute_init(INIT[102*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_67(permute_init(INIT[103*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_68(permute_init(INIT[104*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_69(permute_init(INIT[105*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6A(permute_init(INIT[106*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6B(permute_init(INIT[107*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6C(permute_init(INIT[108*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6D(permute_init(INIT[109*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6E(permute_init(INIT[110*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6F(permute_init(INIT[111*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_70(permute_init(INIT[112*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_71(permute_init(INIT[113*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_72(permute_init(INIT[114*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_73(permute_init(INIT[115*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_74(permute_init(INIT[116*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_75(permute_init(INIT[117*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_76(permute_init(INIT[118*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_77(permute_init(INIT[119*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_78(permute_init(INIT[120*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_79(permute_init(INIT[121*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7A(permute_init(INIT[122*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7B(permute_init(INIT[123*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7C(permute_init(INIT[124*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7D(permute_init(INIT[125*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7E(permute_init(INIT[126*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7F(permute_init(INIT[127*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+`endif
+`ifdef INIT_UPPER
+.INIT_00(permute_init(INIT[128*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_01(permute_init(INIT[129*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_02(permute_init(INIT[130*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_03(permute_init(INIT[131*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_04(permute_init(INIT[132*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_05(permute_init(INIT[133*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_06(permute_init(INIT[134*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_07(permute_init(INIT[135*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_08(permute_init(INIT[136*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_09(permute_init(INIT[137*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0A(permute_init(INIT[138*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0B(permute_init(INIT[139*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0C(permute_init(INIT[140*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0D(permute_init(INIT[141*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0E(permute_init(INIT[142*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_0F(permute_init(INIT[143*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_10(permute_init(INIT[144*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_11(permute_init(INIT[145*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_12(permute_init(INIT[146*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_13(permute_init(INIT[147*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_14(permute_init(INIT[148*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_15(permute_init(INIT[149*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_16(permute_init(INIT[150*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_17(permute_init(INIT[151*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_18(permute_init(INIT[152*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_19(permute_init(INIT[153*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1A(permute_init(INIT[154*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1B(permute_init(INIT[155*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1C(permute_init(INIT[156*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1D(permute_init(INIT[157*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1E(permute_init(INIT[158*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_1F(permute_init(INIT[159*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_20(permute_init(INIT[160*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_21(permute_init(INIT[161*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_22(permute_init(INIT[162*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_23(permute_init(INIT[163*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_24(permute_init(INIT[164*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_25(permute_init(INIT[165*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_26(permute_init(INIT[166*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_27(permute_init(INIT[167*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_28(permute_init(INIT[168*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_29(permute_init(INIT[169*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2A(permute_init(INIT[170*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2B(permute_init(INIT[171*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2C(permute_init(INIT[172*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2D(permute_init(INIT[173*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2E(permute_init(INIT[174*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_2F(permute_init(INIT[175*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_30(permute_init(INIT[176*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_31(permute_init(INIT[177*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_32(permute_init(INIT[178*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_33(permute_init(INIT[179*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_34(permute_init(INIT[180*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_35(permute_init(INIT[181*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_36(permute_init(INIT[182*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_37(permute_init(INIT[183*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_38(permute_init(INIT[184*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_39(permute_init(INIT[185*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3A(permute_init(INIT[186*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3B(permute_init(INIT[187*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3C(permute_init(INIT[188*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3D(permute_init(INIT[189*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3E(permute_init(INIT[190*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_3F(permute_init(INIT[191*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_40(permute_init(INIT[192*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_41(permute_init(INIT[193*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_42(permute_init(INIT[194*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_43(permute_init(INIT[195*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_44(permute_init(INIT[196*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_45(permute_init(INIT[197*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_46(permute_init(INIT[198*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_47(permute_init(INIT[199*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_48(permute_init(INIT[200*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_49(permute_init(INIT[201*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4A(permute_init(INIT[202*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4B(permute_init(INIT[203*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4C(permute_init(INIT[204*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4D(permute_init(INIT[205*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4E(permute_init(INIT[206*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_4F(permute_init(INIT[207*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_50(permute_init(INIT[208*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_51(permute_init(INIT[209*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_52(permute_init(INIT[210*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_53(permute_init(INIT[211*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_54(permute_init(INIT[212*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_55(permute_init(INIT[213*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_56(permute_init(INIT[214*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_57(permute_init(INIT[215*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_58(permute_init(INIT[216*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_59(permute_init(INIT[217*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5A(permute_init(INIT[218*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5B(permute_init(INIT[219*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5C(permute_init(INIT[220*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5D(permute_init(INIT[221*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5E(permute_init(INIT[222*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_5F(permute_init(INIT[223*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_60(permute_init(INIT[224*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_61(permute_init(INIT[225*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_62(permute_init(INIT[226*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_63(permute_init(INIT[227*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_64(permute_init(INIT[228*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_65(permute_init(INIT[229*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_66(permute_init(INIT[230*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_67(permute_init(INIT[231*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_68(permute_init(INIT[232*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_69(permute_init(INIT[233*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6A(permute_init(INIT[234*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6B(permute_init(INIT[235*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6C(permute_init(INIT[236*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6D(permute_init(INIT[237*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6E(permute_init(INIT[238*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_6F(permute_init(INIT[239*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_70(permute_init(INIT[240*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_71(permute_init(INIT[241*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_72(permute_init(INIT[242*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_73(permute_init(INIT[243*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_74(permute_init(INIT[244*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_75(permute_init(INIT[245*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_76(permute_init(INIT[246*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_77(permute_init(INIT[247*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_78(permute_init(INIT[248*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_79(permute_init(INIT[249*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7A(permute_init(INIT[250*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7B(permute_init(INIT[251*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7C(permute_init(INIT[252*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7D(permute_init(INIT[253*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7E(permute_init(INIT[254*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+.INIT_7F(permute_init(INIT[255*INIT_CHUNK_SIZE +: INIT_CHUNK_SIZE])),
+`endif
diff --git a/techlibs/gatemate/brams_map.v b/techlibs/gatemate/brams_map.v
new file mode 100644
index 000000000..f36f05212
--- /dev/null
+++ b/techlibs/gatemate/brams_map.v
@@ -0,0 +1,520 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Cologne Chip AG <support@colognechip.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.
+ *
+ */
+
+module \$__CC_BRAM_20K_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+
+ parameter CFG_ABITS = 14;
+ parameter CFG_DBITS = 40;
+ parameter CFG_ENABLE_A = 1;
+ parameter CFG_ENABLE_B = 1;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+
+ // 512 x 40 bit
+ parameter [20479:0] INIT = 20480'b0;
+
+ input CLK2;
+ input CLK3;
+
+ // write side of the memory
+ input [15:0] A1ADDR;
+ input [39:0] A1DATA;
+ input [39:0] A1EN;
+
+ // read side of the memory
+ input [15:0] B1ADDR;
+ output [39:0] B1DATA;
+ input [0:0] B1EN;
+
+ // unconnected signals
+ wire ECC_1B_ERR, ECC_2B_ERR;
+
+ // internal signals
+ wire [15:0] ADDRA = {A1ADDR, 7'b0};
+ wire [15:0] ADDRB = {B1ADDR, 7'b0};
+
+ localparam INIT_CHUNK_SIZE = 320;
+
+ function [319:0] permute_init;
+ input [INIT_CHUNK_SIZE-1:0] chunk;
+ integer i;
+ begin
+ permute_init = chunk;
+ end
+ endfunction
+
+ CC_BRAM_20K #(
+ `include "brams_init_20.vh"
+ .LOC("UNPLACED"),
+ .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),
+ .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),
+ .RAM_MODE("SDP"),
+ .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),
+ .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),
+ .A_EN_INV(1'b0), .B_EN_INV(1'b0),
+ .A_WE_INV(1'b0), .B_WE_INV(1'b0),
+ .A_DO_REG(1'b0), .B_DO_REG(1'b0),
+ .ECC_EN(1'b0)
+ ) _TECHMAP_REPLACE_ (
+ .A_DO(B1DATA[19:0]),
+ .B_DO(B1DATA[39:20]),
+ .ECC_1B_ERR(ECC_1B_ERR),
+ .ECC_2B_ERR(ECC_2B_ERR),
+ .A_CLK(CLK2),
+ .B_CLK(CLK3),
+ .A_EN(1'b1),
+ .B_EN(B1EN),
+ .A_WE(|A1EN),
+ .B_WE(1'b0),
+ .A_ADDR(ADDRA),
+ .B_ADDR(ADDRB),
+ .A_DI(A1DATA[19:0]),
+ .B_DI(A1DATA[39:20]),
+ .A_BM(A1EN[19:0]),
+ .B_BM(A1EN[39:20])
+ );
+
+endmodule
+
+
+module \$__CC_BRAM_40K_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+
+ parameter CFG_ABITS = 15;
+ parameter CFG_DBITS = 80;
+ parameter CFG_ENABLE_A = 1;
+ parameter CFG_ENABLE_B = 1;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+
+ // 512 x 80 bit
+ parameter [40959:0] INIT = 40960'b0;
+
+ input CLK2;
+ input CLK3;
+
+ // write side of the memory
+ input [15:0] A1ADDR;
+ input [79:0] A1DATA;
+ input [79:0] A1EN;
+
+ // read side of the memory
+ input [15:0] B1ADDR;
+ output [79:0] B1DATA;
+ input [0:0] B1EN;
+
+ // unconnected signals
+ wire A_ECC_1B_ERR, B_ECC_1B_ERR, A_ECC_2B_ERR, B_ECC_2B_ERR;
+
+ // internal signals
+ wire [15:0] ADDRA = {A1ADDR, 7'b0};
+ wire [15:0] ADDRB = {B1ADDR, 7'b0};
+
+ localparam INIT_CHUNK_SIZE = 320;
+
+ function [319:0] permute_init;
+ input [INIT_CHUNK_SIZE-1:0] chunk;
+ integer i;
+ begin
+ permute_init = chunk;
+ end
+ endfunction
+
+ CC_BRAM_40K #(
+ `define INIT_LOWER
+ `include "brams_init_40.vh"
+ `undef INIT_LOWER
+ .LOC("UNPLACED"),
+ .CAS("NONE"),
+ .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),
+ .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),
+ .RAM_MODE("SDP"),
+ .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),
+ .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),
+ .A_EN_INV(1'b0), .B_EN_INV(1'b0),
+ .A_WE_INV(1'b0), .B_WE_INV(1'b0),
+ .A_DO_REG(1'b0), .B_DO_REG(1'b0),
+ .A_ECC_EN(1'b0), .B_ECC_EN(1'b0)
+ ) _TECHMAP_REPLACE_ (
+ .A_DO(B1DATA[39:0]),
+ .B_DO(B1DATA[79:40]),
+ .A_ECC_1B_ERR(A_ECC_1B_ERR),
+ .B_ECC_1B_ERR(B_ECC_1B_ERR),
+ .A_ECC_2B_ERR(A_ECC_2B_ERR),
+ .B_ECC_2B_ERR(B_ECC_2B_ERR),
+ .A_CLK(CLK2),
+ .B_CLK(CLK3),
+ .A_EN(1'b1),
+ .B_EN(B1EN),
+ .A_WE(|A1EN),
+ .B_WE(1'b0),
+ .A_ADDR(ADDRA),
+ .B_ADDR(ADDRB),
+ .A_DI(A1DATA[39:0]),
+ .B_DI(A1DATA[79:40]),
+ .A_BM(A1EN[39:0]),
+ .B_BM(A1EN[79:40])
+ );
+
+endmodule
+
+
+module \$__CC_BRAM_20K_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+
+ parameter CFG_ABITS = 14;
+ parameter CFG_DBITS = 20;
+ parameter CFG_ENABLE_A = 1;
+ parameter CFG_ENABLE_B = 1;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+
+ // 512 x 40 bit
+ parameter [20479:0] INIT = 20480'b0;
+
+ input CLK2;
+ input CLK3;
+
+ // write side of the memory
+ input [15:0] A1ADDR;
+ input [19:0] A1DATA;
+ input [19:0] A1EN;
+
+ // read side of the memory
+ input [15:0] B1ADDR;
+ output [19:0] B1DATA;
+ input [0:0] B1EN;
+
+ // unconnected signals
+ wire [19:0] A_DO;
+ wire ECC_1B_ERR, ECC_2B_ERR;
+
+ localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 2) ? 256 : 320;
+
+ function [319:0] permute_init;
+ input [INIT_CHUNK_SIZE-1:0] chunk;
+ integer i;
+ begin
+ if (CFG_DBITS <= 2) begin
+ for (i = 0; i < 64; i = i + 1) begin
+ permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]};
+ end
+ end else begin
+ permute_init = chunk;
+ end
+ end
+ endfunction
+
+ // internal signals
+ generate
+ wire [15:0] ADDRA;
+ wire [15:0] ADDRB;
+
+ if (CFG_DBITS == 1) begin: blk
+ assign ADDRA = {A1ADDR[13:5], 1'b0, A1ADDR[4:0], 1'b0};
+ assign ADDRB = {B1ADDR[13:5], 1'b0, B1ADDR[4:0], 1'b0};
+ end
+ else if (CFG_DBITS == 2) begin: blk
+ assign ADDRA = {A1ADDR[12:4], 1'b0, A1ADDR[3:0], 2'b0};
+ assign ADDRB = {B1ADDR[12:4], 1'b0, B1ADDR[3:0], 2'b0};
+ end
+ else if (CFG_DBITS == 5) begin: blk
+ assign ADDRA = {A1ADDR[11:3], 1'b0, A1ADDR[2:0], 3'b0};
+ assign ADDRB = {B1ADDR[11:3], 1'b0, B1ADDR[2:0], 3'b0};
+ end
+ else if (CFG_DBITS == 10) begin: blk
+ assign ADDRA = {A1ADDR[10:2], 1'b0, A1ADDR[1:0], 4'b0};
+ assign ADDRB = {B1ADDR[10:2], 1'b0, B1ADDR[1:0], 4'b0};
+ end
+ else if (CFG_DBITS == 20) begin: blk
+ assign ADDRA = {A1ADDR[9:1], 1'b0, A1ADDR[0], 5'b0};
+ assign ADDRB = {B1ADDR[9:1], 1'b0, B1ADDR[0], 5'b0};
+ end
+
+ CC_BRAM_20K #(
+ `include "brams_init_20.vh"
+ .LOC("UNPLACED"),
+ .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),
+ .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),
+ .RAM_MODE("TDP"),
+ .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),
+ .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),
+ .A_EN_INV(1'b0), .B_EN_INV(1'b0),
+ .A_WE_INV(1'b0), .B_WE_INV(1'b0),
+ .A_DO_REG(1'b0), .B_DO_REG(1'b0),
+ .ECC_EN(1'b0)
+ ) _TECHMAP_REPLACE_ (
+ .A_DO(A_DO),
+ .B_DO(B1DATA),
+ .ECC_1B_ERR(ECC_1B_ERR),
+ .ECC_2B_ERR(ECC_2B_ERR),
+ .A_CLK(CLK2),
+ .B_CLK(CLK3),
+ .A_EN(1'b1),
+ .B_EN(B1EN),
+ .A_WE(|A1EN),
+ .B_WE(1'b0),
+ .A_ADDR(ADDRA),
+ .B_ADDR(ADDRB),
+ .A_DI(A1DATA),
+ .B_DI(20'b0),
+ .A_BM(A1EN),
+ .B_BM(20'b0)
+ );
+ endgenerate
+
+endmodule
+
+
+module \$__CC_BRAM_40K_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+
+ parameter CFG_ABITS = 15;
+ parameter CFG_DBITS = 40;
+ parameter CFG_ENABLE_A = 1;
+ parameter CFG_ENABLE_B = 1;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+
+ // 512 x 80 bit
+ parameter [40959:0] INIT = 40960'b0;
+
+ input CLK2;
+ input CLK3;
+
+ // write side of the memory
+ input [15:0] A1ADDR;
+ input [39:0] A1DATA;
+ input [39:0] A1EN;
+
+ // read side of the memory
+ input [15:0] B1ADDR;
+ output [39:0] B1DATA;
+ input [0:0] B1EN;
+
+ // unconnected signals
+ wire [39:0] A_DO;
+ wire A_ECC_1B_ERR, B_ECC_1B_ERR, A_ECC_2B_ERR, B_ECC_2B_ERR;
+
+ localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 2) ? 256 : 320;
+
+ function [319:0] permute_init;
+ input [INIT_CHUNK_SIZE-1:0] chunk;
+ integer i;
+ begin
+ if (CFG_DBITS <= 2) begin
+ for (i = 0; i < 64; i = i + 1) begin
+ permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]};
+ end
+ end else begin
+ permute_init = chunk;
+ end
+ end
+ endfunction
+
+ generate
+ wire [15:0] ADDRA;
+ wire [15:0] ADDRB;
+
+ if (CFG_DBITS == 1) begin
+ assign ADDRA = {A1ADDR, 1'b0};
+ assign ADDRB = {B1ADDR, 1'b0};
+ end
+ else if (CFG_DBITS == 2) begin
+ assign ADDRA = {A1ADDR, 2'b0};
+ assign ADDRB = {B1ADDR, 2'b0};
+ end
+ else if (CFG_DBITS == 5) begin
+ assign ADDRA = {A1ADDR, 3'b0};
+ assign ADDRB = {B1ADDR, 3'b0};
+ end
+ else if (CFG_DBITS == 10) begin
+ assign ADDRA = {A1ADDR, 4'b0};
+ assign ADDRB = {B1ADDR, 4'b0};
+ end
+ else if (CFG_DBITS == 20) begin
+ assign ADDRA = {A1ADDR, 5'b0};
+ assign ADDRB = {B1ADDR, 5'b0};
+ end
+ else if (CFG_DBITS == 40) begin
+ assign ADDRA = {A1ADDR, 6'b0};
+ assign ADDRB = {B1ADDR, 6'b0};
+ end
+
+ CC_BRAM_40K #(
+ `define INIT_LOWER
+ `include "brams_init_40.vh"
+ `undef INIT_LOWER
+ .LOC("UNPLACED"),
+ .CAS("NONE"),
+ .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),
+ .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),
+ .RAM_MODE("TDP"),
+ .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),
+ .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),
+ .A_EN_INV(1'b0), .B_EN_INV(1'b0),
+ .A_WE_INV(1'b0), .B_WE_INV(1'b0),
+ .A_DO_REG(1'b0), .B_DO_REG(1'b0),
+ .A_ECC_EN(1'b0), .B_ECC_EN(1'b0)
+ ) _TECHMAP_REPLACE_ (
+ .A_DO(A_DO),
+ .B_DO(B1DATA),
+ .A_ECC_1B_ERR(A_ECC_1B_ERR),
+ .B_ECC_1B_ERR(B_ECC_1B_ERR),
+ .A_ECC_2B_ERR(A_ECC_2B_ERR),
+ .B_ECC_2B_ERR(B_ECC_2B_ERR),
+ .A_CLK(CLK2),
+ .B_CLK(CLK3),
+ .A_EN(1'b1),
+ .B_EN(B1EN),
+ .A_WE(|A1EN),
+ .B_WE(1'b0),
+ .A_ADDR(ADDRA),
+ .B_ADDR(ADDRB),
+ .A_DI(A1DATA),
+ .B_DI(40'b0),
+ .A_BM(A1EN),
+ .B_BM(40'b0)
+ );
+ endgenerate
+
+endmodule
+
+
+module \$__CC_BRAM_CASCADE (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+
+ parameter CFG_ABITS = 16;
+ parameter CFG_DBITS = 1;
+ parameter CFG_ENABLE_A = 1;
+ parameter CFG_ENABLE_B = 1;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+
+ // 64K x 1
+ parameter [65535:0] INIT = 65535'b0;
+
+ input CLK2;
+ input CLK3;
+
+ // write side of the memory
+ input [15:0] A1ADDR;
+ input [39:0] A1DATA;
+ input [39:0] A1EN;
+
+ // read side of the memory
+ input [15:0] B1ADDR;
+ output [39:0] B1DATA;
+ input [0:0] B1EN;
+
+ // cascade signals
+ wire A_CAS, B_CAS;
+
+ // unconnected signals
+ wire [39:0] A_UP_DO;
+ wire A_ECC_1B_ERR, B_ECC_1B_ERR, A_ECC_2B_ERR, B_ECC_2B_ERR;
+
+ localparam INIT_CHUNK_SIZE = 256;
+
+ function [319:0] permute_init;
+ input [INIT_CHUNK_SIZE-1:0] chunk;
+ integer i;
+ begin
+ for (i = 0; i < 64; i = i + 1) begin
+ permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]};
+ end
+ end
+ endfunction
+
+ generate
+ CC_BRAM_40K #(
+ `define INIT_UPPER
+ `include "brams_init_40.vh" // INIT_80 .. INIT_FF
+ `undef INIT_UPPER
+ .LOC("UNPLACED"),
+ .CAS("UPPER"),
+ .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),
+ .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),
+ .RAM_MODE("TDP"),
+ .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),
+ .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),
+ .A_EN_INV(1'b0), .B_EN_INV(1'b0),
+ .A_WE_INV(1'b0), .B_WE_INV(1'b0),
+ .A_DO_REG(1'b0), .B_DO_REG(1'b0),
+ .A_ECC_EN(1'b0), .B_ECC_EN(1'b0)
+ ) upper_cell (
+ .A_CI(A_CAS),
+ .B_CI(B_CAS),
+ .A_DO(A_UP_DO),
+ .B_DO(B1DATA),
+ .A_ECC_1B_ERR(A_ECC_1B_ERR),
+ .B_ECC_1B_ERR(B_ECC_1B_ERR),
+ .A_ECC_2B_ERR(A_ECC_2B_ERR),
+ .B_ECC_2B_ERR(B_ECC_2B_ERR),
+ .A_CLK(CLK2),
+ .B_CLK(CLK3),
+ .A_EN(1'b1),
+ .B_EN(B1EN),
+ .A_WE(|A1EN),
+ .B_WE(1'b0),
+ .A_ADDR(A1ADDR),
+ .B_ADDR(B1ADDR),
+ .A_DI(A1DATA),
+ .B_DI(40'b0),
+ .A_BM(A1EN),
+ .B_BM(40'b0)
+ );
+
+ CC_BRAM_40K #(
+ `define INIT_LOWER
+ `include "brams_init_40.vh" // INIT_00 .. INIT_7F
+ `undef INIT_LOWER
+ .LOC("UNPLACED"),
+ .CAS("LOWER"),
+ .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),
+ .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),
+ .RAM_MODE("TDP"),
+ .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),
+ .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),
+ .A_EN_INV(1'b0), .B_EN_INV(1'b0),
+ .A_WE_INV(1'b0), .B_WE_INV(1'b0),
+ .A_DO_REG(1'b0), .B_DO_REG(1'b0),
+ .A_ECC_EN(1'b0), .B_ECC_EN(1'b0)
+ ) lower_cell (
+ .A_CI(),
+ .B_CI(),
+ .A_CO(A_CAS),
+ .B_CO(B_CAS),
+ .A_CLK(CLK2),
+ .B_CLK(CLK3),
+ .A_EN(1'b1),
+ .B_EN(B1EN),
+ .A_WE(|A1EN),
+ .B_WE(1'b0),
+ .A_ADDR(A1ADDR),
+ .B_ADDR(B1ADDR),
+ .A_DI(A1DATA),
+ .B_DI(40'b0),
+ .A_BM(A1EN),
+ .B_BM(40'b0)
+ );
+ endgenerate
+
+endmodule
diff --git a/techlibs/gatemate/cells_bb.v b/techlibs/gatemate/cells_bb.v
new file mode 100644
index 000000000..f6fe6a3e1
--- /dev/null
+++ b/techlibs/gatemate/cells_bb.v
@@ -0,0 +1,191 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Cologne Chip AG <support@colognechip.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.
+ *
+ */
+
+(* blackbox *)
+module CC_PLL #(
+ parameter REF_CLK = "", // e.g. "10.0"
+ parameter OUT_CLK = "", // e.g. "50.0"
+ parameter PERF_MD = "", // LOWPOWER, ECONOMY, SPEED
+ parameter LOW_JITTER = 1,
+ parameter CI_FILTER_CONST = 2,
+ parameter CP_FILTER_CONST = 4
+)(
+ input CLK_REF, CLK_FEEDBACK, USR_CLK_REF,
+ input USR_LOCKED_STDY_RST,
+ output USR_PLL_LOCKED_STDY, USR_PLL_LOCKED,
+ output CLK270, CLK180, CLK90, CLK0, CLK_REF_OUT
+);
+endmodule
+
+(* blackbox *)
+module CC_PLL_ADV #(
+ parameter [95:0] PLL_CFG_A = 96'bx,
+ parameter [95:0] PLL_CFG_B = 96'bx
+)(
+ input CLK_REF, CLK_FEEDBACK, USR_CLK_REF,
+ input USR_LOCKED_STDY_RST, USR_SEL_A_B,
+ output USR_PLL_LOCKED_STDY, USR_PLL_LOCKED,
+ output CLK270, CLK180, CLK90, CLK0, CLK_REF_OUT
+);
+endmodule
+
+(* blackbox *) (* keep *)
+module CC_SERDES #(
+ parameter SERDES_CFG = ""
+)(
+ input [63:0] TX_DATA_I,
+ input TX_RESET_I,
+ input TX_PCS_RESET_I,
+ input TX_PMA_RESET_I,
+ input PLL_RESET_I,
+ input TX_POWERDOWN_N_I,
+ input TX_POLARITY_I,
+ input [2:0] TX_PRBS_SEL_I,
+ input TX_PRBS_FORCE_ERR_I,
+ input TX_8B10B_EN_I,
+ input [7:0] TX_8B10B_BYPASS_I,
+ input [7:0] TX_CHAR_IS_K_I,
+ input [7:0] TX_CHAR_DISPMODE_I,
+ input [7:0] TX_CHAR_DISPVAL_I,
+ input TX_ELEC_IDLE_I,
+ input TX_DETECT_RX_I,
+ input [2:0] LOOPBACK_I,
+ input CLK_CORE_TX_I,
+ input CLK_CORE_RX_I,
+ input RX_RESET_I,
+ input RX_PMA_RESET_I,
+ input RX_EQA_RESET_I,
+ input RX_CDR_RESET_I,
+ input RX_PCS_RESET_I,
+ input RX_BUF_RESET_I,
+ input RX_POWERDOWN_N_I,
+ input RX_POLARITY_I,
+ input [2:0] RX_PRBS_SEL_I,
+ input RX_PRBS_CNT_RESET_I,
+ input RX_8B10B_EN_I,
+ input [7:0] RX_8B10B_BYPASS_I,
+ input RX_EN_EI_DETECTOR_I,
+ input RX_COMMA_DETECT_EN_I,
+ input RX_SLIDE_I,
+ input RX_MCOMMA_ALIGN_I,
+ input RX_PCOMMA_ALIGN_I,
+ input CLK_REG_I,
+ input REGFILE_WE_I,
+ input REGFILE_EN_I,
+ input [7:0] REGFILE_ADDR_I,
+ input [15:0] REGFILE_DI_I,
+ input [15:0] REGFILE_MASK_I,
+ output [63:0] RX_DATA_O,
+ output [7:0] RX_NOT_IN_TABLE_O,
+ output [7:0] RX_CHAR_IS_COMMA_O,
+ output [7:0] RX_CHAR_IS_K_O,
+ output [7:0] RX_DISP_ERR_O,
+ output RX_DETECT_DONE_O,
+ output RX_PRESENT_O,
+ output TX_BUF_ERR_O,
+ output TX_RESETDONE_O,
+ output RX_PRBS_ERR_O,
+ output RX_BUF_ERR_O,
+ output RX_BYTE_IS_ALIGNED_O,
+ output RX_BYTE_REALIGN_O,
+ output RX_RESETDONE_O,
+ output RX_EI_EN_O,
+ output CLK_CORE_RX_O,
+ output CLK_CORE_PLL_O,
+ output [15:0] REGFILE_DO_O,
+ output REGFILE_RDY_O
+);
+endmodule
+
+(* blackbox *) (* keep *)
+module CC_CFG_CTRL(
+ input [7:0] DATA,
+ input CLK,
+ input EN,
+ input RECFG,
+ input VALID
+);
+endmodule
+
+(* blackbox *)
+module CC_FIFO_40K (
+ output A_ECC_1B_ERR,
+ output B_ECC_1B_ERR,
+ output A_ECC_2B_ERR,
+ output B_ECC_2B_ERR,
+ // FIFO pop port
+ output [39:0] A_DO,
+ output [39:0] B_DO,
+ (* clkbuf_sink *)
+ input A_CLK,
+ input A_EN,
+ // FIFO push port
+ input [39:0] A_DI,
+ input [39:0] B_DI,
+ input [39:0] A_BM,
+ input [39:0] B_BM,
+ (* clkbuf_sink *)
+ input B_CLK,
+ input B_EN,
+ input B_WE,
+ // FIFO control
+ input F_RST_N,
+ input [12:0] F_ALMOST_FULL_OFFSET,
+ input [12:0] F_ALMOST_EMPTY_OFFSET,
+ // FIFO status signals
+ output F_FULL,
+ output F_EMPTY,
+ output F_ALMOST_FULL,
+ output F_ALMOST_EMPTY,
+ output F_RD_ERROR,
+ output F_WR_ERROR,
+ output [15:0] F_RD_PTR,
+ output [15:0] F_WR_PTR
+);
+ // Location format: D(0..N-1)X(0..3)Y(0..7) or UNPLACED
+ parameter LOC = "UNPLACED";
+
+ // Offset configuration
+ parameter [12:0] ALMOST_FULL_OFFSET = 12'b0;
+ parameter [12:0] ALMOST_EMPTY_OFFSET = 12'b0;
+
+ // Port Widths
+ parameter A_WIDTH = 0;
+ parameter B_WIDTH = 0;
+
+ // RAM and Write Modes
+ parameter RAM_MODE = "SDP"; // "TPD" or "SDP"
+ parameter FIFO_MODE = "SYNC"; // "ASYNC" or "SYNC"
+
+ // Inverting Control Pins
+ parameter A_CLK_INV = 1'b0;
+ parameter B_CLK_INV = 1'b0;
+ parameter A_EN_INV = 1'b0;
+ parameter B_EN_INV = 1'b0;
+ parameter A_WE_INV = 1'b0;
+ parameter B_WE_INV = 1'b0;
+
+ // Output Register
+ parameter A_DO_REG = 1'b0;
+ parameter B_DO_REG = 1'b0;
+
+ // Error Checking and Correction
+ parameter A_ECC_EN = 1'b0;
+ parameter B_ECC_EN = 1'b0;
+endmodule
diff --git a/techlibs/gatemate/cells_sim.v b/techlibs/gatemate/cells_sim.v
new file mode 100644
index 000000000..1de3d1c7a
--- /dev/null
+++ b/techlibs/gatemate/cells_sim.v
@@ -0,0 +1,1411 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Cologne Chip AG <support@colognechip.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.
+ *
+ */
+
+`timescale 1ps/1ps
+
+module CC_IBUF #(
+ parameter PIN_NAME = "UNPLACED",
+ parameter V_IO = "UNDEFINED",
+ parameter [0:0] PULLUP = 1'bx,
+ parameter [0:0] PULLDOWN = 1'bx,
+ parameter [0:0] KEEPER = 1'bx,
+ parameter [0:0] SCHMITT_TRIGGER = 1'bx,
+ // IOSEL
+ parameter [3:0] DELAY_IBF = 1'bx,
+ parameter [0:0] FF_IBF = 1'bx
+)(
+ (* iopad_external_pin *)
+ input I,
+ output Y
+);
+ assign Y = I;
+
+endmodule
+
+
+module CC_OBUF #(
+ parameter PIN_NAME = "UNPLACED",
+ parameter V_IO = "UNDEFINED",
+ parameter DRIVE = "UNDEFINED",
+ parameter SLEW = "UNDEFINED",
+ // IOSEL
+ parameter [3:0] DELAY_OBF = 1'bx,
+ parameter [0:0] FF_OBF = 1'bx
+)(
+ input A,
+ (* iopad_external_pin *)
+ output O
+);
+ assign O = A;
+
+endmodule
+
+
+module CC_TOBUF #(
+ parameter PIN_NAME = "UNPLACED",
+ parameter V_IO = "UNDEFINED",
+ parameter DRIVE = "UNDEFINED",
+ parameter SLEW = "UNDEFINED",
+ parameter [0:0] PULLUP = 1'bx,
+ parameter [0:0] PULLDOWN = 1'bx,
+ parameter [0:0] KEEPER = 1'bx,
+ // IOSEL
+ parameter [3:0] DELAY_OBF = 1'bx,
+ parameter [0:0] FF_OBF = 1'bx
+)(
+ input A, T,
+ (* iopad_external_pin *)
+ output O
+);
+ assign O = T ? 1'bz : A;
+
+endmodule
+
+
+module CC_IOBUF #(
+ parameter PIN_NAME = "UNPLACED",
+ parameter V_IO = "UNDEFINED",
+ parameter DRIVE = "UNDEFINED",
+ parameter SLEW = "UNDEFINED",
+ parameter [0:0] PULLUP = 1'bx,
+ parameter [0:0] PULLDOWN = 1'bx,
+ parameter [0:0] KEEPER = 1'bx,
+ parameter [0:0] SCHMITT_TRIGGER = 1'bx,
+ // IOSEL
+ parameter [3:0] DELAY_IBF = 1'bx,
+ parameter [3:0] DELAY_OBF = 1'bx,
+ parameter [0:0] FF_IBF = 1'bx,
+ parameter [0:0] FF_OBF = 1'bx
+)(
+ input A, T,
+ output Y,
+ (* iopad_external_pin *)
+ inout IO
+);
+ assign IO = T ? 1'bz : A;
+ assign Y = IO;
+
+endmodule
+
+
+module CC_LVDS_IBUF #(
+ parameter PIN_NAME_P = "UNPLACED",
+ parameter PIN_NAME_N = "UNPLACED",
+ parameter V_IO = "UNDEFINED",
+ parameter [0:0] LVDS_RTERM = 1'bx,
+ // IOSEL
+ parameter [3:0] DELAY_IBF = 1'bx,
+ parameter [0:0] FF_IBF = 1'bx
+)(
+ (* iopad_external_pin *)
+ input IP, IN,
+ output Y
+);
+ assign Y = IP;
+
+endmodule
+
+
+module CC_LVDS_OBUF #(
+ parameter PIN_NAME_P = "UNPLACED",
+ parameter PIN_NAME_N = "UNPLACED",
+ parameter V_IO = "UNDEFINED",
+ parameter [0:0] LVDS_BOOST = 1'bx,
+ // IOSEL
+ parameter [3:0] DELAY_OBF = 1'bx,
+ parameter [0:0] FF_OBF = 1'bx
+)(
+ input A,
+ (* iopad_external_pin *)
+ output OP, ON
+);
+ assign OP = A;
+ assign ON = ~A;
+
+endmodule
+
+
+module CC_LVDS_TOBUF #(
+ parameter PIN_NAME_P = "UNPLACED",
+ parameter PIN_NAME_N = "UNPLACED",
+ parameter V_IO = "UNDEFINED",
+ parameter [0:0] LVDS_BOOST = 1'bx,
+ // IOSEL
+ parameter [3:0] DELAY_OBF = 1'bx,
+ parameter [0:0] FF_OBF = 1'bx
+)(
+ input A, T,
+ (* iopad_external_pin *)
+ output OP, ON
+);
+ assign OP = T ? 1'bz : A;
+ assign ON = T ? 1'bz : ~A;
+
+endmodule
+
+
+module CC_LVDS_IOBUF #(
+ parameter PIN_NAME_P = "UNPLACED",
+ parameter PIN_NAME_N = "UNPLACED",
+ parameter V_IO = "UNDEFINED",
+ parameter [0:0] LVDS_RTERM = 1'bx,
+ parameter [0:0] LVDS_BOOST = 1'bx,
+ // IOSEL
+ parameter [3:0] DELAY_IBF = 1'bx,
+ parameter [3:0] DELAY_OBF = 1'bx,
+ parameter [0:0] FF_IBF = 1'bx,
+ parameter [0:0] FF_OBF = 1'bx
+)(
+ input A, T,
+ (* iopad_external_pin *)
+ inout IOP, ION,
+ output Y
+);
+ assign IOP = T ? 1'bz : A;
+ assign ION = T ? 1'bz : ~A;
+ assign Y = IOP;
+
+endmodule
+
+
+module CC_IDDR #(
+ parameter [0:0] CLK_INV = 1'b0
+)(
+ input D,
+ (* clkbuf_sink *)
+ input CLK,
+ output reg Q0, Q1
+);
+ wire clk;
+ assign clk = (CLK_INV) ? ~CLK : CLK;
+
+ always @(posedge clk)
+ begin
+ Q0 <= D;
+ end
+
+ always @(negedge clk)
+ begin
+ Q1 <= D;
+ end
+
+endmodule
+
+
+module CC_ODDR #(
+ parameter [0:0] CLK_INV = 1'b0
+)(
+ input D0,
+ input D1,
+ (* clkbuf_sink *)
+ input CLK,
+ (* clkbuf_sink *)
+ input DDR,
+ output Q
+);
+ wire clk;
+ assign clk = (CLK_INV) ? ~CLK : CLK;
+
+ reg q0, q1;
+ assign Q = (DDR) ? q0 : q1;
+
+ always @(posedge clk)
+ begin
+ q0 <= D0;
+ end
+
+ always @(negedge clk)
+ begin
+ q1 <= D1;
+ end
+
+endmodule
+
+
+module CC_DFF #(
+ parameter [0:0] CLK_INV = 1'b0,
+ parameter [0:0] EN_INV = 1'b0,
+ parameter [0:0] SR_INV = 1'b0,
+ parameter [0:0] SR_VAL = 1'b0
+)(
+ input D,
+ (* clkbuf_sink *)
+ input CLK,
+ input EN,
+ input SR,
+ output reg Q
+);
+ wire clk, en, sr;
+ assign clk = (CLK_INV) ? ~CLK : CLK;
+ assign en = (EN_INV) ? ~EN : EN;
+ assign sr = (SR_INV) ? ~SR : SR;
+
+ initial Q = 1'bX;
+
+ always @(posedge clk or posedge sr)
+ begin
+ if (sr) begin
+ Q <= SR_VAL;
+ end
+ else if (en) begin
+ Q <= D;
+ end
+ end
+
+endmodule
+
+
+module CC_DLT #(
+ parameter [0:0] G_INV = 1'b0,
+ parameter [0:0] SR_INV = 1'b0,
+ parameter [0:0] SR_VAL = 1'b0
+)(
+ input D,
+ input G,
+ input SR,
+ output reg Q
+);
+ wire en, sr;
+ assign en = (G_INV) ? ~G : G;
+ assign sr = (SR_INV) ? ~SR : SR;
+
+ initial Q = 1'bX;
+
+ always @(*)
+ begin
+ if (sr) begin
+ Q <= SR_VAL;
+ end
+ else if (en) begin
+ Q <= D;
+ end
+ end
+
+endmodule
+
+
+module CC_LUT1 (
+ output O,
+ input I0
+);
+ parameter [1:0] INIT = 0;
+
+ assign O = I0 ? INIT[1] : INIT[0];
+
+endmodule
+
+
+module CC_LUT2 (
+ output O,
+ input I0, I1
+);
+ parameter [3:0] INIT = 0;
+
+ wire [1:0] s1 = I1 ? INIT[3:2] : INIT[1:0];
+ assign O = I0 ? s1[1] : s1[0];
+
+endmodule
+
+
+module CC_LUT3 (
+ output O,
+ input I0, I1, I2
+);
+ parameter [7:0] INIT = 0;
+
+ wire [3:0] s2 = I2 ? INIT[7:4] : INIT[3:0];
+ wire [1:0] s1 = I1 ? s2[3:2] : s2[1:0];
+ assign O = I0 ? s1[1] : s1[0];
+
+endmodule
+
+
+module CC_LUT4 (
+ output O,
+ input I0, I1, I2, I3
+);
+ parameter [15:0] INIT = 0;
+
+ wire [7:0] s3 = I3 ? INIT[15:8] : INIT[7:0];
+ wire [3:0] s2 = I2 ? s3[7:4] : s3[3:0];
+ wire [1:0] s1 = I1 ? s2[3:2] : s2[1:0];
+ assign O = I0 ? s1[1] : s1[0];
+
+endmodule
+
+
+module CC_MX2 (
+ input D0, D1,
+ input S0,
+ output Y
+);
+ assign Y = S0 ? D1 : D0;
+
+endmodule
+
+
+module CC_MX4 (
+ input D0, D1, D2, D3,
+ input S0, S1,
+ output Y
+);
+ assign Y = S1 ? (S0 ? D3 : D2) :
+ (S0 ? D1 : D0);
+
+endmodule
+
+
+module CC_MX8 (
+ input D0, D1, D2, D3,
+ input D4, D5, D6, D7,
+ input S0, S1, S2,
+ output Y
+);
+ assign Y = S2 ? (S1 ? (S0 ? D7 : D6) :
+ (S0 ? D5 : D4)) :
+ (S1 ? (S0 ? D3 : D2) :
+ (S0 ? D1 : D0));
+
+endmodule
+
+
+module CC_ADDF (
+ input A, B, CI,
+ output CO, S
+);
+ assign {CO, S} = A + B + CI;
+
+endmodule
+
+
+module CC_MULT #(
+ parameter A_WIDTH = 0,
+ parameter B_WIDTH = 0,
+ parameter P_WIDTH = 0
+)(
+ input signed [A_WIDTH-1:0] A,
+ input signed [B_WIDTH-1:0] B,
+ output reg signed [P_WIDTH-1:0] P
+);
+ always @(*)
+ begin
+ P <= A * B;
+ end
+endmodule
+
+
+module CC_BUFG (
+ input I,
+ (* clkbuf_driver *)
+ output O
+);
+ assign O = I;
+
+endmodule
+
+
+module CC_BRAM_20K (
+ output [19:0] A_DO,
+ output [19:0] B_DO,
+ output ECC_1B_ERR,
+ output ECC_2B_ERR,
+ (* clkbuf_sink *)
+ input A_CLK,
+ (* clkbuf_sink *)
+ input B_CLK,
+ input A_EN,
+ input B_EN,
+ input A_WE,
+ input B_WE,
+ input [15:0] A_ADDR,
+ input [15:0] B_ADDR,
+ input [19:0] A_DI,
+ input [19:0] B_DI,
+ input [19:0] A_BM,
+ input [19:0] B_BM
+);
+ // Location format: D(0..N-1)(0..N-1)X(0..3)Y(0..7)Z(0..1) or UNPLACED
+ parameter LOC = "UNPLACED";
+
+ // Port Widths
+ parameter A_RD_WIDTH = 0;
+ parameter B_RD_WIDTH = 0;
+ parameter A_WR_WIDTH = 0;
+ parameter B_WR_WIDTH = 0;
+
+ // RAM and Write Modes
+ parameter RAM_MODE = "SDP";
+ parameter A_WR_MODE = "NO_CHANGE";
+ parameter B_WR_MODE = "NO_CHANGE";
+
+ // Inverting Control Pins
+ parameter A_CLK_INV = 1'b0;
+ parameter B_CLK_INV = 1'b0;
+ parameter A_EN_INV = 1'b0;
+ parameter B_EN_INV = 1'b0;
+ parameter A_WE_INV = 1'b0;
+ parameter B_WE_INV = 1'b0;
+
+ // Output Register
+ parameter A_DO_REG = 1'b0;
+ parameter B_DO_REG = 1'b0;
+
+ // Error Checking and Correction
+ parameter ECC_EN = 1'b0;
+
+ // RAM Contents
+ parameter INIT_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+
+ localparam WIDTH_MODE_A = (A_RD_WIDTH > A_WR_WIDTH) ? A_RD_WIDTH : A_WR_WIDTH;
+ localparam WIDTH_MODE_B = (B_RD_WIDTH > B_WR_WIDTH) ? B_RD_WIDTH : B_WR_WIDTH;
+
+ integer i, k;
+
+ // 512 x 40 bit
+ reg [20479:0] memory = 20480'b0;
+
+ initial begin
+ // Check parameters
+ if ((RAM_MODE != "SDP") && (RAM_MODE != "TDP")) begin
+ $display("ERROR: Illegal RAM MODE %d.", RAM_MODE);
+ $finish();
+ end
+ if ((A_WR_MODE != "WRITE_THROUGH") && (A_WR_MODE != "NO_CHANGE")) begin
+ $display("ERROR: Illegal RAM MODE %d.", RAM_MODE);
+ $finish();
+ end
+ if ((RAM_MODE == "SDP") && (A_WR_MODE == "WRITE_THROUGH")) begin
+ $display("ERROR: %s is not supported in %s mode.", A_WR_MODE, RAM_MODE);
+ $finish();
+ end
+ if (ECC_EN != 1'b0) begin
+ $display("WARNING: ECC feature not supported in simulation.");
+ end
+ if ((ECC_EN == 1'b1) && (RAM_MODE != "SDP") && (WIDTH_MODE_A != 40)) begin
+ $display("ERROR: Illegal ECC Port configuration. Must be SDP 40 bit, but is %s %d.", RAM_MODE, WIDTH_MODE_A);
+ $finish();
+ end
+ if ((WIDTH_MODE_A == 40) && (RAM_MODE == "TDP")) begin
+ $display("ERROR: Port A width of 40 bits is only supported in SDP mode.");
+ $finish();
+ end
+ if ((WIDTH_MODE_B == 40) && (RAM_MODE == "TDP")) begin
+ $display("ERROR: Port B width of 40 bits is only supported in SDP mode.");
+ $finish();
+ end
+ if ((WIDTH_MODE_A != 40) && (WIDTH_MODE_A != 20) && (WIDTH_MODE_A != 10) &&
+ (WIDTH_MODE_A != 5) && (WIDTH_MODE_A != 2) && (WIDTH_MODE_A != 1) && (WIDTH_MODE_A != 0)) begin
+ $display("ERROR: Illegal %s Port A width configuration %d.", RAM_MODE, WIDTH_MODE_A);
+ $finish();
+ end
+ if ((WIDTH_MODE_B != 40) && (WIDTH_MODE_B != 20) && (WIDTH_MODE_B != 10) &&
+ (WIDTH_MODE_B != 5) && (WIDTH_MODE_B != 2) && (WIDTH_MODE_B != 1) && (WIDTH_MODE_B != 0)) begin
+ $display("ERROR: Illegal %s Port B width configuration %d.", RAM_MODE, WIDTH_MODE_B);
+ $finish();
+ end
+ // RAM initialization
+ memory[320*0+319:320*0] = INIT_00;
+ memory[320*1+319:320*1] = INIT_01;
+ memory[320*2+319:320*2] = INIT_02;
+ memory[320*3+319:320*3] = INIT_03;
+ memory[320*4+319:320*4] = INIT_04;
+ memory[320*5+319:320*5] = INIT_05;
+ memory[320*6+319:320*6] = INIT_06;
+ memory[320*7+319:320*7] = INIT_07;
+ memory[320*8+319:320*8] = INIT_08;
+ memory[320*9+319:320*9] = INIT_09;
+ memory[320*10+319:320*10] = INIT_0A;
+ memory[320*11+319:320*11] = INIT_0B;
+ memory[320*12+319:320*12] = INIT_0C;
+ memory[320*13+319:320*13] = INIT_0D;
+ memory[320*14+319:320*14] = INIT_0E;
+ memory[320*15+319:320*15] = INIT_0F;
+ memory[320*16+319:320*16] = INIT_10;
+ memory[320*17+319:320*17] = INIT_11;
+ memory[320*18+319:320*18] = INIT_12;
+ memory[320*19+319:320*19] = INIT_13;
+ memory[320*20+319:320*20] = INIT_14;
+ memory[320*21+319:320*21] = INIT_15;
+ memory[320*22+319:320*22] = INIT_16;
+ memory[320*23+319:320*23] = INIT_17;
+ memory[320*24+319:320*24] = INIT_18;
+ memory[320*25+319:320*25] = INIT_19;
+ memory[320*26+319:320*26] = INIT_1A;
+ memory[320*27+319:320*27] = INIT_1B;
+ memory[320*28+319:320*28] = INIT_1C;
+ memory[320*29+319:320*29] = INIT_1D;
+ memory[320*30+319:320*30] = INIT_1E;
+ memory[320*31+319:320*31] = INIT_1F;
+ memory[320*32+319:320*32] = INIT_20;
+ memory[320*33+319:320*33] = INIT_21;
+ memory[320*34+319:320*34] = INIT_22;
+ memory[320*35+319:320*35] = INIT_23;
+ memory[320*36+319:320*36] = INIT_24;
+ memory[320*37+319:320*37] = INIT_25;
+ memory[320*38+319:320*38] = INIT_26;
+ memory[320*39+319:320*39] = INIT_27;
+ memory[320*40+319:320*40] = INIT_28;
+ memory[320*41+319:320*41] = INIT_29;
+ memory[320*42+319:320*42] = INIT_2A;
+ memory[320*43+319:320*43] = INIT_2B;
+ memory[320*44+319:320*44] = INIT_2C;
+ memory[320*45+319:320*45] = INIT_2D;
+ memory[320*46+319:320*46] = INIT_2E;
+ memory[320*47+319:320*47] = INIT_2F;
+ memory[320*48+319:320*48] = INIT_30;
+ memory[320*49+319:320*49] = INIT_31;
+ memory[320*50+319:320*50] = INIT_32;
+ memory[320*51+319:320*51] = INIT_33;
+ memory[320*52+319:320*52] = INIT_34;
+ memory[320*53+319:320*53] = INIT_35;
+ memory[320*54+319:320*54] = INIT_36;
+ memory[320*55+319:320*55] = INIT_37;
+ memory[320*56+319:320*56] = INIT_38;
+ memory[320*57+319:320*57] = INIT_39;
+ memory[320*58+319:320*58] = INIT_3A;
+ memory[320*59+319:320*59] = INIT_3B;
+ memory[320*60+319:320*60] = INIT_3C;
+ memory[320*61+319:320*61] = INIT_3D;
+ memory[320*62+319:320*62] = INIT_3E;
+ memory[320*63+319:320*63] = INIT_3F;
+ end
+
+ // Signal inversion
+ wire clka = A_CLK_INV ^ A_CLK;
+ wire clkb = B_CLK_INV ^ B_CLK;
+ wire ena = A_EN_INV ^ A_EN;
+ wire enb = B_EN_INV ^ B_EN;
+ wire wea = A_WE_INV ^ A_WE;
+ wire web = B_WE_INV ^ B_WE;
+
+ // Internal signals
+ wire [15:0] addra;
+ wire [15:0] addrb;
+ reg [19:0] A_DO_out = 0, A_DO_reg = 0;
+ reg [19:0] B_DO_out = 0, B_DO_reg = 0;
+
+ generate
+ if (RAM_MODE == "SDP") begin
+ // Port A (write)
+ if (A_WR_WIDTH == 40) begin
+ assign addra = A_ADDR[15:7]*40;
+ end
+ // Port B (read)
+ if (B_RD_WIDTH == 40) begin
+ assign addrb = B_ADDR[15:7]*40;
+ end
+ end
+ else if (RAM_MODE == "TDP") begin
+ // Port A
+ if (WIDTH_MODE_A <= 1) begin
+ wire [15:0] tmpa = {2'b0, A_ADDR[15:7], A_ADDR[5:1]};
+ assign addra = tmpa + (tmpa/4);
+ end
+ else if (WIDTH_MODE_A <= 2) begin
+ wire [15:0] tmpa = {3'b0, A_ADDR[15:7], A_ADDR[5:2]};
+ assign addra = tmpa*2 + (tmpa/2);
+ end
+ else if (WIDTH_MODE_A <= 5) begin
+ assign addra = {4'b0, A_ADDR[15:7], A_ADDR[5:3]}*5;
+ end
+ else if (WIDTH_MODE_A <= 10) begin
+ assign addra = {5'b0, A_ADDR[15:7], A_ADDR[5:4]}*10;
+ end
+ else if (WIDTH_MODE_A <= 20) begin
+ assign addra = {6'b0, A_ADDR[15:7], A_ADDR[5]}*20;
+ end
+ // Port B
+ if (WIDTH_MODE_B <= 1) begin
+ wire [15:0] tmpb = {2'b0, B_ADDR[15:7], B_ADDR[5:1]};
+ assign addrb = tmpb + (tmpb/4);
+ end
+ else if (WIDTH_MODE_B <= 2) begin
+ wire [15:0] tmpb = {3'b0, B_ADDR[15:7], B_ADDR[5:2]};
+ assign addrb = tmpb*2 + (tmpb/2);
+ end
+ else if (WIDTH_MODE_B <= 5) begin
+ assign addrb = {4'b0, B_ADDR[15:7], B_ADDR[5:3]}*5;
+ end
+ else if (WIDTH_MODE_B <= 10) begin
+ assign addrb = {5'b0, B_ADDR[15:7], B_ADDR[5:4]}*10;
+ end
+ else if (WIDTH_MODE_B <= 20) begin
+ assign addrb = {6'b0, B_ADDR[15:7], B_ADDR[5]}*20;
+ end
+ end
+ endgenerate
+
+ generate
+ if (RAM_MODE == "SDP") begin
+ // SDP write port
+ always @(posedge clka)
+ begin
+ for (k=0; k < A_WR_WIDTH; k=k+1) begin
+ if (k < 20) begin
+ if (ena && wea && A_BM[k]) memory[addra+k] <= A_DI[k];
+ end
+ else begin // use both ports
+ if (ena && wea && B_BM[k-20]) memory[addra+k] <= B_DI[k-20];
+ end
+ end
+ end
+ // SDP read port
+ always @(posedge clkb)
+ begin
+ // "NO_CHANGE" only
+ for (k=0; k < B_RD_WIDTH; k=k+1) begin
+ if (k < 20) begin
+ if (enb && !wea) A_DO_out[k] <= memory[addrb+k];
+ end
+ else begin // use both ports
+ if (enb && !wea) B_DO_out[k-20] <= memory[addrb+k];
+ end
+ end
+ end
+ end
+ else if (RAM_MODE == "TDP") begin
+ // TDP port A
+ always @(posedge clka)
+ begin
+ for (i=0; i < WIDTH_MODE_A; i=i+1) begin
+ if (ena && wea && A_BM[i]) memory[addra+i] <= A_DI[i];
+
+ if (A_WR_MODE == "NO_CHANGE") begin
+ if (ena && !wea) A_DO_out[i] <= memory[addra+i];
+ end
+ else if (A_WR_MODE == "WRITE_THROUGH") begin
+ if (ena) begin
+ if (wea && A_BM[i]) begin
+ A_DO_out[i] <= A_DI[i];
+ end
+ else begin
+ A_DO_out[i] <= memory[addra+i];
+ end
+ end
+ end
+ end
+ end
+ // TDP port B
+ always @(posedge clkb)
+ begin
+ for (i=0; i < WIDTH_MODE_B; i=i+1) begin
+ if (enb && web && B_BM[i]) memory[addrb+i] <= B_DI[i];
+
+ if (B_WR_MODE == "NO_CHANGE") begin
+ if (enb && !web) B_DO_out[i] <= memory[addrb+i];
+ end
+ else if (B_WR_MODE == "WRITE_THROUGH") begin
+ if (enb) begin
+ if (web && B_BM[i]) begin
+ B_DO_out[i] <= B_DI[i];
+ end
+ else begin
+ B_DO_out[i] <= memory[addrb+i];
+ end
+ end
+ end
+ end
+ end
+ end
+ endgenerate
+
+ // Optional output register
+ generate
+ if (A_DO_REG) begin
+ always @(posedge clka) begin
+ A_DO_reg <= A_DO_out;
+ end
+ assign A_DO = A_DO_reg;
+ end
+ else begin
+ assign A_DO = A_DO_out;
+ end
+ if (B_DO_REG) begin
+ always @(posedge clkb) begin
+ B_DO_reg <= B_DO_out;
+ end
+ assign B_DO = B_DO_reg;
+ end
+ else begin
+ assign B_DO = B_DO_out;
+ end
+ endgenerate
+endmodule
+
+
+module CC_BRAM_40K (
+ output [39:0] A_DO,
+ output [39:0] B_DO,
+ output A_ECC_1B_ERR,
+ output B_ECC_1B_ERR,
+ output A_ECC_2B_ERR,
+ output B_ECC_2B_ERR,
+ output reg A_CO = 0,
+ output reg B_CO = 0,
+ (* clkbuf_sink *)
+ input A_CLK,
+ (* clkbuf_sink *)
+ input B_CLK,
+ input A_EN,
+ input B_EN,
+ input A_WE,
+ input B_WE,
+ input [15:0] A_ADDR,
+ input [15:0] B_ADDR,
+ input [39:0] A_DI,
+ input [39:0] B_DI,
+ input [39:0] A_BM,
+ input [39:0] B_BM,
+ input A_CI,
+ input B_CI
+);
+ // Location format: D(0..N-1)X(0..3)Y(0..7) or UNPLACED
+ parameter LOC = "UNPLACED";
+ parameter CAS = "NONE"; // NONE, UPPER, LOWER
+
+ // Port Widths
+ parameter A_RD_WIDTH = 0;
+ parameter B_RD_WIDTH = 0;
+ parameter A_WR_WIDTH = 0;
+ parameter B_WR_WIDTH = 0;
+
+ // RAM and Write Modes
+ parameter RAM_MODE = "SDP";
+ parameter A_WR_MODE = "NO_CHANGE";
+ parameter B_WR_MODE = "NO_CHANGE";
+
+ // Inverting Control Pins
+ parameter A_CLK_INV = 1'b0;
+ parameter B_CLK_INV = 1'b0;
+ parameter A_EN_INV = 1'b0;
+ parameter B_EN_INV = 1'b0;
+ parameter A_WE_INV = 1'b0;
+ parameter B_WE_INV = 1'b0;
+
+ // Output Register
+ parameter A_DO_REG = 1'b0;
+ parameter B_DO_REG = 1'b0;
+
+ // Error Checking and Correction
+ parameter A_ECC_EN = 1'b0;
+ parameter B_ECC_EN = 1'b0;
+
+ parameter INIT_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_40 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_41 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_42 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_43 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_44 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_45 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_46 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_47 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_48 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_49 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_4A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_4B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_4C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_4D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_4E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_4F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_50 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_51 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_52 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_53 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_54 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_55 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_56 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_57 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_58 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_59 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_5A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_5B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_5C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_5D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_5E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_5F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_60 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_61 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_62 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_63 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_64 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_65 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_66 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_67 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_68 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_69 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_6A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_6B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_6C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_6D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_6E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_6F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_70 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_71 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_72 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_73 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_74 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_75 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_76 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_77 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_78 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_79 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_7A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_7B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_7C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_7D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_7E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INIT_7F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+
+ localparam WIDTH_MODE_A = (A_RD_WIDTH > A_WR_WIDTH) ? A_RD_WIDTH : A_WR_WIDTH;
+ localparam WIDTH_MODE_B = (B_RD_WIDTH > B_WR_WIDTH) ? B_RD_WIDTH : B_WR_WIDTH;
+
+ integer i, k;
+
+ // 512 x 80 bit
+ reg [40959:0] memory = 40960'b0;
+
+ initial begin
+ // Check parameters
+ if ((RAM_MODE != "SDP") && (RAM_MODE != "TDP")) begin
+ $display("ERROR: Illegal RAM MODE %d.", RAM_MODE);
+ $finish();
+ end
+ if ((A_WR_MODE != "WRITE_THROUGH") && (A_WR_MODE != "NO_CHANGE")) begin
+ $display("ERROR: Illegal RAM MODE %d.", RAM_MODE);
+ $finish();
+ end
+ if ((RAM_MODE == "SDP") && (A_WR_MODE == "WRITE_THROUGH")) begin
+ $display("ERROR: %s is not supported in %s mode.", A_WR_MODE, RAM_MODE);
+ $finish();
+ end
+ if ((A_ECC_EN != 1'b0) || (B_ECC_EN != 1'b0)) begin
+ $display("WARNING: ECC feature not supported in simulation.");
+ end
+ if ((A_ECC_EN == 1'b1) && (RAM_MODE != "SDP") && (WIDTH_MODE_A != 40)) begin
+ $display("ERROR: Illegal ECC Port A configuration. Must be SDP 40 bit, but is %s %d.", RAM_MODE, WIDTH_MODE_A);
+ $finish();
+ end
+ if ((WIDTH_MODE_A == 80) && (RAM_MODE == "TDP")) begin
+ $display("ERROR: Port A width of 80 bits is only supported in SDP mode.");
+ $finish();
+ end
+ if ((WIDTH_MODE_B == 80) && (RAM_MODE == "TDP")) begin
+ $display("ERROR: Port B width of 80 bits is only supported in SDP mode.");
+ $finish();
+ end
+ if ((WIDTH_MODE_A != 80) && (WIDTH_MODE_A != 40) && (WIDTH_MODE_A != 20) && (WIDTH_MODE_A != 10) &&
+ (WIDTH_MODE_A != 5) && (WIDTH_MODE_A != 2) && (WIDTH_MODE_A != 1) && (WIDTH_MODE_A != 0)) begin
+ $display("ERROR: Illegal %s Port A width configuration %d.", RAM_MODE, WIDTH_MODE_A);
+ $finish();
+ end
+ if ((WIDTH_MODE_B != 80) && (WIDTH_MODE_B != 40) && (WIDTH_MODE_B != 20) && (WIDTH_MODE_B != 10) &&
+ (WIDTH_MODE_B != 5) && (WIDTH_MODE_B != 2) && (WIDTH_MODE_B != 1) && (WIDTH_MODE_B != 0)) begin
+ $display("ERROR: Illegal %s Port B width configuration %d.", RAM_MODE, WIDTH_MODE_B);
+ $finish();
+ end
+ if ((CAS != "NONE") && ((WIDTH_MODE_A > 1) || (WIDTH_MODE_B > 1))) begin
+ $display("ERROR: Cascade feature only supported in 1 bit data width mode.");
+ $finish();
+ end
+ if ((CAS != "NONE") && (RAM_MODE != "TDP")) begin
+ $display("ERROR: Cascade feature only supported in TDP mode.");
+ $finish();
+ end
+ // RAM initialization
+ memory[320*0+319:320*0] = INIT_00;
+ memory[320*1+319:320*1] = INIT_01;
+ memory[320*2+319:320*2] = INIT_02;
+ memory[320*3+319:320*3] = INIT_03;
+ memory[320*4+319:320*4] = INIT_04;
+ memory[320*5+319:320*5] = INIT_05;
+ memory[320*6+319:320*6] = INIT_06;
+ memory[320*7+319:320*7] = INIT_07;
+ memory[320*8+319:320*8] = INIT_08;
+ memory[320*9+319:320*9] = INIT_09;
+ memory[320*10+319:320*10] = INIT_0A;
+ memory[320*11+319:320*11] = INIT_0B;
+ memory[320*12+319:320*12] = INIT_0C;
+ memory[320*13+319:320*13] = INIT_0D;
+ memory[320*14+319:320*14] = INIT_0E;
+ memory[320*15+319:320*15] = INIT_0F;
+ memory[320*16+319:320*16] = INIT_10;
+ memory[320*17+319:320*17] = INIT_11;
+ memory[320*18+319:320*18] = INIT_12;
+ memory[320*19+319:320*19] = INIT_13;
+ memory[320*20+319:320*20] = INIT_14;
+ memory[320*21+319:320*21] = INIT_15;
+ memory[320*22+319:320*22] = INIT_16;
+ memory[320*23+319:320*23] = INIT_17;
+ memory[320*24+319:320*24] = INIT_18;
+ memory[320*25+319:320*25] = INIT_19;
+ memory[320*26+319:320*26] = INIT_1A;
+ memory[320*27+319:320*27] = INIT_1B;
+ memory[320*28+319:320*28] = INIT_1C;
+ memory[320*29+319:320*29] = INIT_1D;
+ memory[320*30+319:320*30] = INIT_1E;
+ memory[320*31+319:320*31] = INIT_1F;
+ memory[320*32+319:320*32] = INIT_20;
+ memory[320*33+319:320*33] = INIT_21;
+ memory[320*34+319:320*34] = INIT_22;
+ memory[320*35+319:320*35] = INIT_23;
+ memory[320*36+319:320*36] = INIT_24;
+ memory[320*37+319:320*37] = INIT_25;
+ memory[320*38+319:320*38] = INIT_26;
+ memory[320*39+319:320*39] = INIT_27;
+ memory[320*40+319:320*40] = INIT_28;
+ memory[320*41+319:320*41] = INIT_29;
+ memory[320*42+319:320*42] = INIT_2A;
+ memory[320*43+319:320*43] = INIT_2B;
+ memory[320*44+319:320*44] = INIT_2C;
+ memory[320*45+319:320*45] = INIT_2D;
+ memory[320*46+319:320*46] = INIT_2E;
+ memory[320*47+319:320*47] = INIT_2F;
+ memory[320*48+319:320*48] = INIT_30;
+ memory[320*49+319:320*49] = INIT_31;
+ memory[320*50+319:320*50] = INIT_32;
+ memory[320*51+319:320*51] = INIT_33;
+ memory[320*52+319:320*52] = INIT_34;
+ memory[320*53+319:320*53] = INIT_35;
+ memory[320*54+319:320*54] = INIT_36;
+ memory[320*55+319:320*55] = INIT_37;
+ memory[320*56+319:320*56] = INIT_38;
+ memory[320*57+319:320*57] = INIT_39;
+ memory[320*58+319:320*58] = INIT_3A;
+ memory[320*59+319:320*59] = INIT_3B;
+ memory[320*60+319:320*60] = INIT_3C;
+ memory[320*61+319:320*61] = INIT_3D;
+ memory[320*62+319:320*62] = INIT_3E;
+ memory[320*63+319:320*63] = INIT_3F;
+ memory[320*64+319:320*64] = INIT_40;
+ memory[320*65+319:320*65] = INIT_41;
+ memory[320*66+319:320*66] = INIT_42;
+ memory[320*67+319:320*67] = INIT_43;
+ memory[320*68+319:320*68] = INIT_44;
+ memory[320*69+319:320*69] = INIT_45;
+ memory[320*70+319:320*70] = INIT_46;
+ memory[320*71+319:320*71] = INIT_47;
+ memory[320*72+319:320*72] = INIT_48;
+ memory[320*73+319:320*73] = INIT_49;
+ memory[320*74+319:320*74] = INIT_4A;
+ memory[320*75+319:320*75] = INIT_4B;
+ memory[320*76+319:320*76] = INIT_4C;
+ memory[320*77+319:320*77] = INIT_4D;
+ memory[320*78+319:320*78] = INIT_4E;
+ memory[320*79+319:320*79] = INIT_4F;
+ memory[320*80+319:320*80] = INIT_50;
+ memory[320*81+319:320*81] = INIT_51;
+ memory[320*82+319:320*82] = INIT_52;
+ memory[320*83+319:320*83] = INIT_53;
+ memory[320*84+319:320*84] = INIT_54;
+ memory[320*85+319:320*85] = INIT_55;
+ memory[320*86+319:320*86] = INIT_56;
+ memory[320*87+319:320*87] = INIT_57;
+ memory[320*88+319:320*88] = INIT_58;
+ memory[320*89+319:320*89] = INIT_59;
+ memory[320*90+319:320*90] = INIT_5A;
+ memory[320*91+319:320*91] = INIT_5B;
+ memory[320*92+319:320*92] = INIT_5C;
+ memory[320*93+319:320*93] = INIT_5D;
+ memory[320*94+319:320*94] = INIT_5E;
+ memory[320*95+319:320*95] = INIT_5F;
+ memory[320*96+319:320*96] = INIT_60;
+ memory[320*97+319:320*97] = INIT_61;
+ memory[320*98+319:320*98] = INIT_62;
+ memory[320*99+319:320*99] = INIT_63;
+ memory[320*100+319:320*100] = INIT_64;
+ memory[320*101+319:320*101] = INIT_65;
+ memory[320*102+319:320*102] = INIT_66;
+ memory[320*103+319:320*103] = INIT_67;
+ memory[320*104+319:320*104] = INIT_68;
+ memory[320*105+319:320*105] = INIT_69;
+ memory[320*106+319:320*106] = INIT_6A;
+ memory[320*107+319:320*107] = INIT_6B;
+ memory[320*108+319:320*108] = INIT_6C;
+ memory[320*109+319:320*109] = INIT_6D;
+ memory[320*110+319:320*110] = INIT_6E;
+ memory[320*111+319:320*111] = INIT_6F;
+ memory[320*112+319:320*112] = INIT_70;
+ memory[320*113+319:320*113] = INIT_71;
+ memory[320*114+319:320*114] = INIT_72;
+ memory[320*115+319:320*115] = INIT_73;
+ memory[320*116+319:320*116] = INIT_74;
+ memory[320*117+319:320*117] = INIT_75;
+ memory[320*118+319:320*118] = INIT_76;
+ memory[320*119+319:320*119] = INIT_77;
+ memory[320*120+319:320*120] = INIT_78;
+ memory[320*121+319:320*121] = INIT_79;
+ memory[320*122+319:320*122] = INIT_7A;
+ memory[320*123+319:320*123] = INIT_7B;
+ memory[320*124+319:320*124] = INIT_7C;
+ memory[320*125+319:320*125] = INIT_7D;
+ memory[320*126+319:320*126] = INIT_7E;
+ memory[320*127+319:320*127] = INIT_7F;
+ end
+
+ // Signal inversion
+ wire clka = A_CLK_INV ^ A_CLK;
+ wire clkb = B_CLK_INV ^ B_CLK;
+ wire ena = A_EN_INV ^ A_EN;
+ wire enb = B_EN_INV ^ B_EN;
+ wire wea = A_WE_INV ^ A_WE;
+ wire web = B_WE_INV ^ B_WE;
+
+ // Internal signals
+ wire [15:0] addra;
+ wire [15:0] addrb;
+ reg [39:0] A_DO_out = 0, A_DO_reg = 0;
+ reg [39:0] B_DO_out = 0, B_DO_reg = 0;
+
+ generate
+ if (RAM_MODE == "SDP") begin
+ // Port A (write)
+ if (A_WR_WIDTH == 80) begin
+ assign addra = A_ADDR[15:7]*80;
+ end
+ // Port B (read)
+ if (B_RD_WIDTH == 80) begin
+ assign addrb = B_ADDR[15:7]*80;
+ end
+ end
+ else if (RAM_MODE == "TDP") begin
+ // Port A
+ if (WIDTH_MODE_A <= 1) begin
+ wire [15:0] tmpa = {1'b0, A_ADDR[15:1]};
+ assign addra = tmpa + (tmpa/4);
+ end
+ else if (WIDTH_MODE_A <= 2) begin
+ wire [15:0] tmpa = {2'b0, A_ADDR[15:2]};
+ assign addra = tmpa*2 + (tmpa/2);
+ end
+ else if (WIDTH_MODE_A <= 5) begin
+ assign addra = {3'b0, A_ADDR[15:3]}*5;
+ end
+ else if (WIDTH_MODE_A <= 10) begin
+ assign addra = {4'b0, A_ADDR[15:4]}*10;
+ end
+ else if (WIDTH_MODE_A <= 20) begin
+ assign addra = {5'b0, A_ADDR[15:5]}*20;
+ end
+ else if (WIDTH_MODE_A <= 40) begin
+ assign addra = {6'b0, A_ADDR[15:6]}*40;
+ end
+ // Port B
+ if (WIDTH_MODE_B <= 1) begin
+ wire [15:0] tmpb = {1'b0, B_ADDR[15:1]};
+ assign addrb = tmpb + (tmpb/4);
+ end
+ else if (WIDTH_MODE_B <= 2) begin
+ wire [15:0] tmpb = {2'b0, B_ADDR[15:2]};
+ assign addrb = tmpb*2 + (tmpb/2);
+ end
+ else if (WIDTH_MODE_B <= 5) begin
+ assign addrb = {3'b0, B_ADDR[15:3]}*5;
+ end
+ else if (WIDTH_MODE_B <= 10) begin
+ assign addrb = {4'b0, B_ADDR[15:4]}*10;
+ end
+ else if (WIDTH_MODE_B <= 20) begin
+ assign addrb = {5'b0, B_ADDR[15:5]}*20;
+ end
+ else if (WIDTH_MODE_B <= 40) begin
+ assign addrb = {6'b0, B_ADDR[15:6]}*40;
+ end
+ end
+ endgenerate
+
+ generate
+ if (RAM_MODE == "SDP") begin
+ // SDP write port
+ always @(posedge clka)
+ begin
+ for (k=0; k < A_WR_WIDTH; k=k+1) begin
+ if (k < 40) begin
+ if (ena && wea && A_BM[k]) memory[addra+k] <= A_DI[k];
+ end
+ else begin // use both ports
+ if (ena && wea && B_BM[k-40]) memory[addra+k] <= B_DI[k-40];
+ end
+ end
+ end
+ // SDP read port
+ always @(posedge clkb)
+ begin
+ // "NO_CHANGE" only
+ for (k=0; k < B_RD_WIDTH; k=k+1) begin
+ if (k < 40) begin
+ if (enb && !wea) A_DO_out[k] <= memory[addrb+k];
+ end
+ else begin // use both ports
+ if (enb && !wea) B_DO_out[k-40] <= memory[addrb+k];
+ end
+ end
+ end
+ end
+ else if (RAM_MODE == "TDP") begin
+ // {A,B}_ADDR[0]=0 selects lower, {A,B}_ADDR[0]=1 selects upper cascade memory
+ wire upper_sel_a = ((CAS == "UPPER") && (A_ADDR[0] == 1));
+ wire lower_sel_a = ((CAS == "LOWER") && (A_ADDR[0] == 0));
+ wire upper_sel_b = ((CAS == "UPPER") && (B_ADDR[0] == 1));
+ wire lower_sel_b = ((CAS == "LOWER") && (B_ADDR[0] == 0));
+
+ reg dumm;
+
+ // Cascade output port A
+ always @(*)
+ begin
+ if ((A_WR_MODE == "NO_CHANGE") && lower_sel_a) begin
+ A_CO = memory[addra];
+ end
+ else if ((A_WR_MODE == "WRITE_THROUGH") && lower_sel_a) begin
+ A_CO = ((wea && A_BM[0]) ? (A_DI[0]) : (memory[addra]));
+ end
+ end
+
+ // Cascade output port B
+ always @(*)
+ begin
+ if ((B_WR_MODE == "NO_CHANGE") && lower_sel_b) begin
+ B_CO = memory[addrb];
+ end
+ else if ((B_WR_MODE == "WRITE_THROUGH") && lower_sel_b) begin
+ B_CO = ((web && B_BM[0]) ? (B_DI[0]) : (memory[addrb]));
+ end
+ end
+
+ // TDP port A
+ always @(posedge clka)
+ begin
+ for (i=0; i < WIDTH_MODE_A; i=i+1) begin
+ if (upper_sel_a || lower_sel_a || (CAS == "NONE")) begin
+ if (ena && wea && A_BM[i])
+ memory[addra+i] <= A_DI[i];
+ end
+
+ if (A_WR_MODE == "NO_CHANGE") begin
+ if (ena && !wea) begin
+ if (CAS == "UPPER") begin
+ A_DO_out[i] <= ((A_ADDR[0] == 1) ? (memory[addra+i]) : (A_CI));
+ end
+ else if (CAS == "NONE") begin
+ A_DO_out[i] <= memory[addra+i];
+ end
+ end
+ end
+ else if (A_WR_MODE == "WRITE_THROUGH") begin
+ if (ena) begin
+ if (CAS == "UPPER") begin
+ if (A_ADDR[0] == 1) begin
+ A_DO_out[i] <= ((wea && A_BM[i]) ? (A_DI[i]) : (memory[addra+i]));
+ end else begin
+ A_DO_out[i] <= A_CI;
+ end
+ end
+ else if (CAS == "NONE") begin
+ A_DO_out[i] <= ((wea && A_BM[i]) ? (A_DI[i]) : (memory[addra+i]));
+ end
+ end
+ end
+ end
+ end
+ // TDP port B
+ always @(posedge clkb)
+ begin
+ for (i=0; i < WIDTH_MODE_B; i=i+1) begin
+ if (upper_sel_b || lower_sel_b || (CAS == "NONE")) begin
+ if (enb && web && B_BM[i])
+ memory[addrb+i] <= B_DI[i];
+ end
+
+ if (B_WR_MODE == "NO_CHANGE") begin
+ if (enb && !web) begin
+ if (CAS == "UPPER") begin
+ B_DO_out[i] <= ((B_ADDR[0] == 1) ? (memory[addrb+i]) : (B_CI));
+ end
+ else if (CAS == "NONE") begin
+ B_DO_out[i] <= memory[addrb+i];
+ end
+ end
+ end
+ else if (B_WR_MODE == "WRITE_THROUGH") begin
+ if (enb) begin
+ if (CAS == "UPPER") begin
+ if (B_ADDR[0] == 1) begin
+ B_DO_out[i] <= ((web && B_BM[i]) ? (B_DI[i]) : (memory[addrb+i]));
+ end else begin
+ B_DO_out[i] <= B_CI;
+ end
+ end
+ else if (CAS == "NONE") begin
+ B_DO_out[i] <= ((web && B_BM[i]) ? (B_DI[i]) : (memory[addrb+i]));
+ end
+ end
+ end
+ end
+ end
+ end
+ endgenerate
+
+ // Optional output register
+ generate
+ if (A_DO_REG) begin
+ always @(posedge clka) begin
+ A_DO_reg <= A_DO_out;
+ end
+ assign A_DO = A_DO_reg;
+ end
+ else begin
+ assign A_DO = A_DO_out;
+ end
+ if (B_DO_REG) begin
+ always @(posedge clkb) begin
+ B_DO_reg <= B_DO_out;
+ end
+ assign B_DO = B_DO_reg;
+ end
+ else begin
+ assign B_DO = B_DO_out;
+ end
+ endgenerate
+endmodule
diff --git a/techlibs/gatemate/lut_map.v b/techlibs/gatemate/lut_map.v
new file mode 100644
index 000000000..1e5d49725
--- /dev/null
+++ b/techlibs/gatemate/lut_map.v
@@ -0,0 +1,45 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Cologne Chip AG <support@colognechip.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.
+ *
+ */
+
+module \$lut (A, Y);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+
+ (* force_downto *)
+ input [WIDTH-1:0] A;
+ output Y;
+
+ generate
+ if (WIDTH == 1) begin
+ CC_LUT1 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]));
+ end
+ else if (WIDTH == 2) begin
+ CC_LUT2 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]));
+ end
+ else if (WIDTH == 3) begin
+ CC_LUT3 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]));
+ end
+ else if (WIDTH == 4) begin
+ CC_LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.O(Y), .I0(A[0]), .I1(A[1]), .I2(A[2]), .I3(A[3]));
+ end
+ else begin
+ wire _TECHMAP_FAIL_ = 1;
+ end
+ endgenerate
+endmodule
diff --git a/techlibs/gatemate/mul_map.v b/techlibs/gatemate/mul_map.v
new file mode 100644
index 000000000..c2dd0a9b4
--- /dev/null
+++ b/techlibs/gatemate/mul_map.v
@@ -0,0 +1,77 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Cologne Chip AG <support@colognechip.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.
+ *
+ */
+
+(* techmap_celltype = "$mul $__mul" *)
+module \$__MULMXN (A, B, Y);
+
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+ parameter A_WIDTH = 1;
+ parameter B_WIDTH = 1;
+ parameter Y_WIDTH = 1;
+
+ (* force_downto *)
+ input [A_WIDTH-1:0] A;
+ (* force_downto *)
+ input [B_WIDTH-1:0] B;
+ (* force_downto *)
+ output [Y_WIDTH-1:0] Y;
+
+ localparam A_ADJWIDTH = A_WIDTH + (A_SIGNED ? 0 : 1);
+ localparam B_ADJWIDTH = B_WIDTH + (B_SIGNED ? 0 : 1);
+
+ generate
+ if (A_SIGNED) begin: blkA
+ wire signed [A_ADJWIDTH-1:0] Aext = $signed(A);
+ end
+ else begin: blkA
+ wire [A_ADJWIDTH-1:0] Aext = A;
+ end
+ if (B_SIGNED) begin: blkB
+ wire signed [B_ADJWIDTH-1:0] Bext = $signed(B);
+ end
+ else begin: blkB
+ wire [B_ADJWIDTH-1:0] Bext = B;
+ end
+
+ if (A_WIDTH >= B_WIDTH) begin
+ CC_MULT #(
+ .A_WIDTH(A_ADJWIDTH),
+ .B_WIDTH(B_ADJWIDTH),
+ .P_WIDTH(Y_WIDTH),
+ ) _TECHMAP_REPLACE_ (
+ .A(blkA.Aext),
+ .B(blkB.Bext),
+ .P(Y)
+ );
+ end
+ else begin // swap A,B
+ CC_MULT #(
+ .A_WIDTH(B_ADJWIDTH),
+ .B_WIDTH(A_ADJWIDTH),
+ .P_WIDTH(Y_WIDTH),
+ ) _TECHMAP_REPLACE_ (
+ .A(blkB.Bext),
+ .B(blkA.Aext),
+ .P(Y)
+ );
+ end
+ endgenerate
+
+endmodule
diff --git a/techlibs/gatemate/mux_map.v b/techlibs/gatemate/mux_map.v
new file mode 100644
index 000000000..13c1972e3
--- /dev/null
+++ b/techlibs/gatemate/mux_map.v
@@ -0,0 +1,56 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Cologne Chip AG <support@colognechip.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.
+ *
+ */
+
+module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y);
+ input A, B, C, D, E, F, G, H, S, T, U;
+ output Y;
+
+ CC_MX8 _TECHMAP_REPLACE_ (
+ .D0(A), .D1(B), .D2(C), .D3(D),
+ .D4(E), .D5(F), .D6(G), .D7(H),
+ .S0(S), .S1(T), .S2(U),
+ .Y(Y)
+ );
+
+endmodule
+
+module \$_MUX4_ (A, B, C, D, S, T, Y);
+ input A, B, C, D, S, T;
+ output Y;
+
+ CC_MX4 _TECHMAP_REPLACE_ (
+ .D0(A), .D1(B), .D2(C), .D3(D),
+ .S0(S), .S1(T),
+ .Y(Y)
+ );
+
+endmodule
+
+/*
+module \$_MUX_ (A, B, S, Y);
+ input A, B, S;
+ output Y;
+
+ CC_MX2 _TECHMAP_REPLACE_ (
+ .D0(A), .D1(B), .S0(S),
+ .Y(Y)
+ );
+
+endmodule
+*/
diff --git a/techlibs/gatemate/reg_map.v b/techlibs/gatemate/reg_map.v
new file mode 100644
index 000000000..6a2c7fb91
--- /dev/null
+++ b/techlibs/gatemate/reg_map.v
@@ -0,0 +1,45 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Cologne Chip AG <support@colognechip.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.
+ *
+ */
+
+(* techmap_celltype = "$_DFFE_[NP][NP][01][NP]_" *)
+module \$_DFFE_xxxx_ (input D, C, R, E, output Q);
+
+ parameter _TECHMAP_CELLTYPE_ = "";
+
+ CC_DFF #(
+ .CLK_INV(_TECHMAP_CELLTYPE_[39:32] == "N"),
+ .EN_INV(_TECHMAP_CELLTYPE_[15:8] == "N"),
+ .SR_INV(_TECHMAP_CELLTYPE_[31:24] == "N"),
+ .SR_VAL(_TECHMAP_CELLTYPE_[23:16] == "1")
+ ) _TECHMAP_REPLACE_ (.D(D), .EN(E), .CLK(C), .SR(R), .Q(Q));
+
+endmodule
+
+(* techmap_celltype = "$_DLATCH_[NP][NP][01]_" *)
+module \$_DLATCH_xxx_ (input E, R, D, output Q);
+
+ parameter _TECHMAP_CELLTYPE_ = "";
+
+ CC_DLT #(
+ .G_INV(_TECHMAP_CELLTYPE_[31:24] == "N"),
+ .SR_INV(_TECHMAP_CELLTYPE_[23:16] == "N"),
+ .SR_VAL(_TECHMAP_CELLTYPE_[15:8] == "1")
+ ) _TECHMAP_REPLACE_ (.D(D), .G(E), .SR(R), .Q(Q));
+
+endmodule
diff --git a/techlibs/gatemate/synth_gatemate.cc b/techlibs/gatemate/synth_gatemate.cc
new file mode 100644
index 000000000..0131cdcdf
--- /dev/null
+++ b/techlibs/gatemate/synth_gatemate.cc
@@ -0,0 +1,351 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 Cologne Chip AG <support@colognechip.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 "kernel/register.h"
+#include "kernel/celltypes.h"
+#include "kernel/rtlil.h"
+#include "kernel/log.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct SynthGateMatePass : public ScriptPass
+{
+ SynthGateMatePass() : ScriptPass("synth_gatemate", "synthesis for Cologne Chip GateMate FPGAs") { }
+
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" synth_gatemate [options]\n");
+ log("\n");
+ log("This command runs synthesis for Cologne Chip AG GateMate FPGAs.\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module.\n");
+ log("\n");
+ log(" -vlog <file>\n");
+ log(" write the design to the specified verilog file. Writing of an output\n");
+ log(" file is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -json <file>\n");
+ log(" write the design to the specified JSON file. Writing of an output file\n");
+ log(" is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -run <from_label>:<to_label>\n");
+ log(" only run the commands between the labels (see below). An empty\n");
+ log(" from label is synonymous to 'begin', and empty to label is\n");
+ log(" synonymous to the end of the command list.\n");
+ log("\n");
+ log(" -noflatten\n");
+ log(" do not flatten design before synthesis.\n");
+ log("\n");
+ log(" -nobram\n");
+ log(" do not use CC_BRAM_20K or CC_BRAM_40K cells in output netlist.\n");
+ log("\n");
+ log(" -noaddf\n");
+ log(" do not use CC_ADDF full adder cells in output netlist.\n");
+ log("\n");
+ log(" -nomult\n");
+ log(" do not use CC_MULT multiplier cells in output netlist.\n");
+ log("\n");
+ log(" -nomx8, -nomx4\n");
+ log(" do not use CC_MX{8,4} multiplexer cells in output netlist.\n");
+ log("\n");;
+ log(" -dff\n");
+ log(" run 'abc' with -dff option\n");
+ log("\n");
+ log(" -retime\n");
+ log(" run 'abc' with '-dff -D 1' options\n");
+ log("\n");
+ log(" -noiopad\n");
+ log(" disable I/O buffer insertion (useful for hierarchical or \n");
+ log(" out-of-context flows).\n");
+ log("\n");
+ log(" -noclkbuf\n");
+ log(" disable automatic clock buffer insertion.\n");
+ log("\n");
+ log("The following commands are executed by this synthesis command:\n");
+ help_script();
+ log("\n");
+ }
+
+ string top_opt, vlog_file, json_file;
+ bool noflatten, nobram, noaddf, nomult, nomx4, nomx8, dff, retime, noiopad, noclkbuf;
+
+ void clear_flags() override
+ {
+ top_opt = "-auto-top";
+ vlog_file = "";
+ json_file = "";
+ noflatten = false;
+ nobram = false;
+ noaddf = false;
+ nomult = false;
+ nomx4 = false;
+ nomx8 = false;
+ dff = false;
+ retime = false;
+ noiopad = false;
+ noclkbuf = false;
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ string run_from, run_to;
+ clear_flags();
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-top" && argidx+1 < args.size()) {
+ top_opt = "-top " + args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-vlog" && argidx+1 < args.size()) {
+ vlog_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-json" && argidx+1 < args.size()) {
+ json_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-run" && argidx+1 < args.size()) {
+ size_t pos = args[argidx+1].find(':');
+ if (pos == std::string::npos)
+ break;
+ run_from = args[++argidx].substr(0, pos);
+ run_to = args[argidx].substr(pos+1);
+ continue;
+ }
+ if (args[argidx] == "-noflatten") {
+ noflatten = true;
+ continue;
+ }
+ if (args[argidx] == "-nobram") {
+ nobram = true;
+ continue;
+ }
+ if (args[argidx] == "-noaddf") {
+ noaddf = true;
+ continue;
+ }
+ if (args[argidx] == "-nomult") {
+ nomult = true;
+ continue;
+ }
+ if (args[argidx] == "-nomx4") {
+ nomx4 = true;
+ continue;
+ }
+ if (args[argidx] == "-nomx8") {
+ nomx8 = true;
+ continue;
+ }
+ if (args[argidx] == "-dff") {
+ dff = true;
+ continue;
+ }
+ if (args[argidx] == "-retime") {
+ retime = true;
+ continue;
+ }
+ if (args[argidx] == "-noiopad") {
+ noiopad = true;
+ continue;
+ }
+ if (args[argidx] == "-noclkbuf") {
+ noclkbuf = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (!design->full_selection()) {
+ log_cmd_error("This command only operates on fully selected designs!\n");
+ }
+
+ log_header(design, "Executing SYNTH_GATEMATE pass.\n");
+ log_push();
+
+ run_script(design, run_from, run_to);
+
+ log_pop();
+ }
+
+ void script() override
+ {
+ if (check_label("begin"))
+ {
+ run("read_verilog -lib -specify +/gatemate/cells_sim.v +/gatemate/cells_bb.v");
+ run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
+ }
+
+ if (check_label("prepare"))
+ {
+ run("proc");
+ if (!noflatten) {
+ run("flatten");
+ }
+ run("tribuf -logic");
+ run("deminout");
+ run("opt_expr");
+ run("opt_clean");
+ run("check");
+ run("opt -nodffe -nosdff");
+ run("fsm");
+ run("opt");
+ run("wreduce");
+ run("peepopt");
+ run("opt_clean");
+ run("muxpack");
+ run("share");
+ run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
+ run("opt_expr");
+ run("opt_clean");
+ }
+
+ if (check_label("map_mult", "(skip if '-nomult')") && !nomult)
+ {
+ run("techmap -map +/gatemate/mul_map.v");
+ }
+
+ if (check_label("coarse"))
+ {
+ run("alumacc");
+ run("opt");
+ run("memory -nomap");
+ run("opt_clean");
+ }
+
+ if (check_label("map_bram", "(skip if '-nobram')") && !nobram)
+ {
+ run("memory_bram -rules +/gatemate/brams.txt");
+ run("setundef -zero -params "
+ "t:$__CC_BRAM_CASCADE "
+ "t:$__CC_BRAM_40K_SDP t:$__CC_BRAM_20K_SDP "
+ "t:$__CC_BRAM_20K_TDP t:$__CC_BRAM_40K_TDP "
+ );
+ run("techmap -map +/gatemate/brams_map.v");
+ }
+
+ if (check_label("map_ffram"))
+ {
+ run("opt -fast -mux_undef -undriven -fine");
+ run("memory_map");
+ run("opt -undriven -fine");
+ }
+
+ if (check_label("map_gates"))
+ {
+ std::string techmap_args = "";
+ if (!noaddf) {
+ techmap_args += " -map +/gatemate/arith_map.v";
+ }
+ run("techmap -map +/techmap.v " + techmap_args);
+ run("opt -fast");
+ if (retime) {
+ run("abc -dff -D 1", "(only if -retime)");
+ }
+ }
+
+ if (check_label("map_io", "(skip if '-noiopad')") && !noiopad)
+ {
+ run("iopadmap -bits "
+ "-inpad CC_IBUF Y:I "
+ "-outpad CC_OBUF A:O "
+ "-toutpad CC_TOBUF ~T:A:O "
+ "-tinoutpad CC_IOBUF ~T:Y:A:IO"
+ );
+ run("clean");
+ }
+
+ if (check_label("map_regs"))
+ {
+ run("opt_clean");
+ run("dfflegalize -cell $_DFFE_????_ x -cell $_DLATCH_???_ x");
+ run("techmap -map +/gatemate/reg_map.v");
+ run("opt_expr -mux_undef");
+ run("simplemap");
+ run("opt_clean");
+ }
+
+ if (check_label("map_muxs"))
+ {
+ std::string muxcover_args;
+ if (!nomx4) {
+ muxcover_args += stringf(" -mux4");
+ }
+ if (!nomx8) {
+ muxcover_args += stringf(" -mux8");
+ }
+ run("muxcover " + muxcover_args);
+ run("opt -full");
+ run("techmap -map +/gatemate/mux_map.v");
+ }
+
+ if (check_label("map_luts"))
+ {
+ std::string abc_args = " -dress -lut 4";
+ if (dff) {
+ abc_args += " -dff";
+ }
+ run("abc " + abc_args);
+ run("clean");
+ }
+
+ if (check_label("map_cells"))
+ {
+ run("techmap -map +/gatemate/lut_map.v");
+ run("clean");
+ }
+
+ if (check_label("map_bufg", "(skip if '-noclkbuf')") && !noclkbuf)
+ {
+ run("clkbufmap -buf CC_BUFG O:I");
+ run("clean");
+ }
+
+ if (check_label("check"))
+ {
+ run("hierarchy -check");
+ run("stat -width");
+ run("check -noinit");
+ run("blackbox =A:whitebox");
+ }
+
+ if (check_label("vlog"))
+ {
+ run("opt_clean -purge");
+ if (!vlog_file.empty() || help_mode) {
+ run(stringf("write_verilog -noattr %s", help_mode ? "<file-name>" : vlog_file.c_str()));
+ }
+ }
+
+ if (check_label("json"))
+ {
+ if (!json_file.empty() || help_mode) {
+ run(stringf("write_json %s", help_mode ? "<file-name>" : json_file.c_str()));
+ }
+ }
+ }
+} SynthGateMatePass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/gowin/arith_map.v b/techlibs/gowin/arith_map.v
index 42aaba870..2d48fa752 100644
--- a/techlibs/gowin/arith_map.v
+++ b/techlibs/gowin/arith_map.v
@@ -1,8 +1,8 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
- * Copyright (C) 2018 David Shah <dave@ds0.me>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
+ * Copyright (C) 2018 gatecat <gatecat@ds0.me>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
diff --git a/techlibs/gowin/cells_map.v b/techlibs/gowin/cells_map.v
index 851ef20b2..5978a00d0 100644
--- a/techlibs/gowin/cells_map.v
+++ b/techlibs/gowin/cells_map.v
@@ -122,7 +122,6 @@ module \$_DFFE_NP0P_ (input D, C, R, E, output Q);
wire _TECHMAP_REMOVEINIT_Q_ = 1;
endmodule
-
module \$lut (A, Y);
parameter WIDTH = 0;
parameter LUT = 0;
diff --git a/techlibs/gowin/cells_sim.v b/techlibs/gowin/cells_sim.v
index 509bf3ef2..bb4b9e5c5 100644
--- a/techlibs/gowin/cells_sim.v
+++ b/techlibs/gowin/cells_sim.v
@@ -573,14 +573,14 @@ endmodule
module TBUF (O, I, OEN);
input I, OEN;
output O;
- assign O = OEN ? I : 1'bz;
+ assign O = OEN ? 1'bz : I;
endmodule
module IOBUF (O, IO, I, OEN);
input I,OEN;
output O;
inout IO;
- assign IO = OEN ? I : 1'bz;
+ assign IO = OEN ? 1'bz : I;
assign I = IO;
endmodule
@@ -674,51 +674,250 @@ end
endmodule
+
+module RAM16S1 (DO, DI, AD, WRE, CLK);
+
+parameter INIT_0 = 16'h0000;
+
+input [3:0] AD;
+input DI;
+output DO;
+input CLK;
+input WRE;
+
+specify
+ (AD *> DO) = (270, 405);
+ $setup(DI, posedge CLK, 62);
+ $setup(WRE, posedge CLK, 62);
+ $setup(AD, posedge CLK, 62);
+ (posedge CLK => (DO : 1'bx)) = (474, 565);
+endspecify
+
+reg [15:0] mem;
+
+initial begin
+ mem = INIT_0;
+end
+
+assign DO = mem[AD];
+
+always @(posedge CLK) begin
+ if (WRE) begin
+ mem[AD] <= DI;
+ end
+end
+
+endmodule
+
+
+module RAM16S2 (DO, DI, AD, WRE, CLK);
+
+parameter INIT_0 = 16'h0000;
+parameter INIT_1 = 16'h0000;
+
+input [3:0] AD;
+input [1:0] DI;
+output [1:0] DO;
+input CLK;
+input WRE;
+
+specify
+ (AD *> DO) = (270, 405);
+ $setup(DI, posedge CLK, 62);
+ $setup(WRE, posedge CLK, 62);
+ $setup(AD, posedge CLK, 62);
+ (posedge CLK => (DO : 2'bx)) = (474, 565);
+endspecify
+
+reg [15:0] mem0, mem1;
+
+initial begin
+ mem0 = INIT_0;
+ mem1 = INIT_1;
+end
+
+assign DO[0] = mem0[AD];
+assign DO[1] = mem1[AD];
+
+always @(posedge CLK) begin
+ if (WRE) begin
+ mem0[AD] <= DI[0];
+ mem1[AD] <= DI[1];
+ end
+end
+
+endmodule
+
+
module RAM16S4 (DO, DI, AD, WRE, CLK);
- parameter WIDTH = 4;
- parameter INIT_0 = 16'h0000;
- parameter INIT_1 = 16'h0000;
- parameter INIT_2 = 16'h0000;
- parameter INIT_3 = 16'h0000;
-
- input [WIDTH-1:0] AD;
- input [WIDTH-1:0] DI;
- output [WIDTH-1:0] DO;
- input CLK;
- input WRE;
- specify
- (AD => DO) = (270, 405);
+parameter INIT_0 = 16'h0000;
+parameter INIT_1 = 16'h0000;
+parameter INIT_2 = 16'h0000;
+parameter INIT_3 = 16'h0000;
+
+input [3:0] AD;
+input [3:0] DI;
+output [3:0] DO;
+input CLK;
+input WRE;
+
+specify
+ (AD *> DO) = (270, 405);
$setup(DI, posedge CLK, 62);
$setup(WRE, posedge CLK, 62);
$setup(AD, posedge CLK, 62);
- (posedge CLK => (DO : {WIDTH{1'bx}})) = (474, 565);
- endspecify
+ (posedge CLK => (DO : 4'bx)) = (474, 565);
+endspecify
+
+reg [15:0] mem0, mem1, mem2, mem3;
+
+initial begin
+ mem0 = INIT_0;
+ mem1 = INIT_1;
+ mem2 = INIT_2;
+ mem3 = INIT_3;
+end
+
+assign DO[0] = mem0[AD];
+assign DO[1] = mem1[AD];
+assign DO[2] = mem2[AD];
+assign DO[3] = mem3[AD];
+
+always @(posedge CLK) begin
+ if (WRE) begin
+ mem0[AD] <= DI[0];
+ mem1[AD] <= DI[1];
+ mem2[AD] <= DI[2];
+ mem3[AD] <= DI[3];
+ end
+end
+
+endmodule
- reg [15:0] mem0, mem1, mem2, mem3;
-
- initial begin
- mem0 = INIT_0;
- mem1 = INIT_1;
- mem2 = INIT_2;
- mem3 = INIT_3;
- end
-
- assign DO[0] = mem0[AD];
- assign DO[1] = mem1[AD];
- assign DO[2] = mem2[AD];
- assign DO[3] = mem3[AD];
-
- always @(posedge CLK) begin
- if (WRE) begin
- mem0[AD] <= DI[0];
- mem1[AD] <= DI[1];
- mem2[AD] <= DI[2];
- mem3[AD] <= DI[3];
- end
- end
-
-endmodule // RAM16S4
+
+module RAM16SDP1 (DO, DI, WAD, RAD, WRE, CLK);
+
+parameter INIT_0 = 16'h0000;
+
+input [3:0] WAD;
+input [3:0] RAD;
+input DI;
+output DO;
+input CLK;
+input WRE;
+
+specify
+ (RAD *> DO) = (270, 405);
+ $setup(DI, posedge CLK, 62);
+ $setup(WRE, posedge CLK, 62);
+ $setup(WAD, posedge CLK, 62);
+ (posedge CLK => (DO : 1'bx)) = (474, 565);
+endspecify
+
+reg [15:0] mem;
+
+initial begin
+ mem = INIT_0;
+end
+
+assign DO = mem[RAD];
+
+always @(posedge CLK) begin
+ if (WRE) begin
+ mem[WAD] <= DI;
+ end
+end
+
+endmodule
+
+
+module RAM16SDP2 (DO, DI, WAD, RAD, WRE, CLK);
+
+parameter INIT_0 = 16'h0000;
+parameter INIT_1 = 16'h0000;
+
+input [3:0] WAD;
+input [3:0] RAD;
+input [1:0] DI;
+output [1:0] DO;
+input CLK;
+input WRE;
+
+specify
+ (RAD *> DO) = (270, 405);
+ $setup(DI, posedge CLK, 62);
+ $setup(WRE, posedge CLK, 62);
+ $setup(WAD, posedge CLK, 62);
+ (posedge CLK => (DO : 2'bx)) = (474, 565);
+endspecify
+
+reg [15:0] mem0, mem1;
+
+initial begin
+ mem0 = INIT_0;
+ mem1 = INIT_1;
+end
+
+assign DO[0] = mem0[RAD];
+assign DO[1] = mem1[RAD];
+
+always @(posedge CLK) begin
+ if (WRE) begin
+ mem0[WAD] <= DI[0];
+ mem1[WAD] <= DI[1];
+ end
+end
+
+endmodule
+
+
+module RAM16SDP4 (DO, DI, WAD, RAD, WRE, CLK);
+
+parameter INIT_0 = 16'h0000;
+parameter INIT_1 = 16'h0000;
+parameter INIT_2 = 16'h0000;
+parameter INIT_3 = 16'h0000;
+
+input [3:0] WAD;
+input [3:0] RAD;
+input [3:0] DI;
+output [3:0] DO;
+input CLK;
+input WRE;
+
+specify
+ (RAD *> DO) = (270, 405);
+ $setup(DI, posedge CLK, 62);
+ $setup(WRE, posedge CLK, 62);
+ $setup(WAD, posedge CLK, 62);
+ (posedge CLK => (DO : 4'bx)) = (474, 565);
+endspecify
+
+reg [15:0] mem0, mem1, mem2, mem3;
+
+initial begin
+ mem0 = INIT_0;
+ mem1 = INIT_1;
+ mem2 = INIT_2;
+ mem3 = INIT_3;
+end
+
+assign DO[0] = mem0[RAD];
+assign DO[1] = mem1[RAD];
+assign DO[2] = mem2[RAD];
+assign DO[3] = mem3[RAD];
+
+always @(posedge CLK) begin
+ if (WRE) begin
+ mem0[WAD] <= DI[0];
+ mem1[WAD] <= DI[1];
+ mem2[WAD] <= DI[2];
+ mem3[WAD] <= DI[3];
+ end
+end
+
+endmodule
(* blackbox *)
diff --git a/techlibs/gowin/lutrams_map.v b/techlibs/gowin/lutrams_map.v
index a50ab365a..e5daab6ae 100644
--- a/techlibs/gowin/lutrams_map.v
+++ b/techlibs/gowin/lutrams_map.v
@@ -15,13 +15,14 @@ module \$__GW1NR_RAM16S4 (CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
`include "brams_init3.vh"
- RAM16S4
+ RAM16SDP4
#(.INIT_0(INIT_0),
.INIT_1(INIT_1),
.INIT_2(INIT_2),
.INIT_3(INIT_3))
_TECHMAP_REPLACE_
- (.AD(B1ADDR),
+ (.WAD(B1ADDR),
+ .RAD(A1ADDR),
.DI(B1DATA),
.DO(A1DATA),
.CLK(CLK1),
diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc
index 5bf0894da..cfbc9b9a6 100644
--- a/techlibs/gowin/synth_gowin.cc
+++ b/techlibs/gowin/synth_gowin.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -126,8 +126,6 @@ struct SynthGowinPass : public ScriptPass
json_file = args[++argidx];
nobram = true;
nolutram = true;
- nowidelut = true;
- noalu = true;
continue;
}
if (args[argidx] == "-run" && argidx+1 < args.size()) {
@@ -240,7 +238,9 @@ struct SynthGowinPass : public ScriptPass
run("opt -fast");
if (retime || help_mode)
run("abc -dff -D 1", "(only if -retime)");
- run("splitnets");
+ if (!noiopads || help_mode)
+ run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O "
+ "-toutpad TBUF ~OEN:I:O -tinoutpad IOBUF ~OEN:O:I:IO", "(unless -noiopads)");
}
if (check_label("map_ffs"))
@@ -277,9 +277,8 @@ struct SynthGowinPass : public ScriptPass
run("opt_lut_ins -tech gowin");
run("setundef -undriven -params -zero");
run("hilomap -singleton -hicell VCC V -locell GND G");
- if (!noiopads || help_mode)
- run("iopadmap -bits -inpad IBUF O:I -outpad OBUF I:O "
- "-toutpad TBUF OEN:I:O -tinoutpad IOBUF OEN:O:I:IO", "(unless -noiopads)");
+ if (!vout_file.empty() || help_mode) // vendor output requires 1-bit wires
+ run("splitnets -ports", "(only if -vout used)");
run("clean");
run("autoname");
}
@@ -289,12 +288,13 @@ struct SynthGowinPass : public ScriptPass
run("hierarchy -check");
run("stat");
run("check -noinit");
+ run("blackbox =A:whitebox");
}
if (check_label("vout"))
{
if (!vout_file.empty() || help_mode)
- run(stringf("write_verilog -decimal -attr2comment -defparam -renameprefix gen %s",
+ run(stringf("write_verilog -simple-lhs -decimal -attr2comment -defparam -renameprefix gen %s",
help_mode ? "<file-name>" : vout_file.c_str()));
if (!json_file.empty() || help_mode)
run(stringf("write_json %s",
diff --git a/techlibs/greenpak4/greenpak4_dffinv.cc b/techlibs/greenpak4/greenpak4_dffinv.cc
index b8797bc19..a77711e01 100644
--- a/techlibs/greenpak4/greenpak4_dffinv.cc
+++ b/techlibs/greenpak4/greenpak4_dffinv.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/greenpak4/synth_greenpak4.cc b/techlibs/greenpak4/synth_greenpak4.cc
index d9af340d9..a9f7db679 100644
--- a/techlibs/greenpak4/synth_greenpak4.cc
+++ b/techlibs/greenpak4/synth_greenpak4.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -196,6 +196,7 @@ struct SynthGreenPAK4Pass : public ScriptPass
run("hierarchy -check");
run("stat");
run("check -noinit");
+ run("blackbox =A:whitebox");
}
if (check_label("json"))
diff --git a/techlibs/ice40/abc9_model.v b/techlibs/ice40/abc9_model.v
index 84923d381..3e3ca94a6 100644
--- a/techlibs/ice40/abc9_model.v
+++ b/techlibs/ice40/abc9_model.v
@@ -28,57 +28,57 @@ module \$__ICE40_CARRY_WRAPPER (
);
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L79
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L79
(CI => CO) = (126, 105);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L80
(I0 => O) = (449, 386);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L82
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L82
(A => CO) = (259, 245);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L83
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L83
(A => O) = (400, 379);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L85
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L85
(B => CO) = (231, 133);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L86
(B => O) = (379, 351);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L88
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L88
(I3 => O) = (316, 288);
(CI => O) = (316, 288);
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L79
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L79
(CI => CO) = (186, 155);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L80
(I0 => O) = (662, 569);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L82
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L82
(A => CO) = (382, 362);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L83
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L83
(A => O) = (589, 558);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L85
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L85
(B => CO) = (341, 196);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L86
(B => O) = (558, 517);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L88
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L88
(I3 => O) = (465, 423);
(CI => O) = (465, 423);
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L91
(CI => CO) = (278, 278);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L92
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L92
(I0 => O) = (1245, 1285);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L94
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L94
(A => CO) = (675, 662);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L95
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L95
(A => O) = (1179, 1232);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L97
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L97
(B => CO) = (609, 358);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L98
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L98
(B => O) = (1179, 1205);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L100
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L100
(I3 => O) = (861, 874);
(CI => O) = (861, 874);
endspecify
diff --git a/techlibs/ice40/arith_map.v b/techlibs/ice40/arith_map.v
index 3950e882b..087220ec2 100644
--- a/techlibs/ice40/arith_map.v
+++ b/techlibs/ice40/arith_map.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/ice40/cells_sim.v b/techlibs/ice40/cells_sim.v
index 7ee809262..2e1c6807a 100644
--- a/techlibs/ice40/cells_sim.v
+++ b/techlibs/ice40/cells_sim.v
@@ -1,13 +1,23 @@
`timescale 1ps / 1ps
-`define SB_DFF_REG reg Q = 0
-// `define SB_DFF_REG reg Q
+`define SB_DFF_INIT initial Q = 0;
+// `define SB_DFF_INIT
+
+`ifndef NO_ICE40_DEFAULT_ASSIGNMENTS
+`define ICE40_DEFAULT_ASSIGNMENT_V(v) = v
+`define ICE40_DEFAULT_ASSIGNMENT_0 = 1'b0
+`define ICE40_DEFAULT_ASSIGNMENT_1 = 1'b1
+`else
+`define ICE40_DEFAULT_ASSIGNMENT_V(v)
+`define ICE40_DEFAULT_ASSIGNMENT_0
+`define ICE40_DEFAULT_ASSIGNMENT_1
+`endif
// SiliconBlue IO Cells
module SB_IO (
inout PACKAGE_PIN,
input LATCH_INPUT_VALUE,
- input CLOCK_ENABLE,
+ input CLOCK_ENABLE `ICE40_DEFAULT_ASSIGNMENT_1,
input INPUT_CLK,
input OUTPUT_CLK,
input OUTPUT_ENABLE,
@@ -114,7 +124,7 @@ module SB_GB_IO (
inout PACKAGE_PIN,
output GLOBAL_BUFFER_OUTPUT,
input LATCH_INPUT_VALUE,
- input CLOCK_ENABLE,
+ input CLOCK_ENABLE `ICE40_DEFAULT_ASSIGNMENT_1,
input INPUT_CLK,
input OUTPUT_CLK,
input OUTPUT_ENABLE,
@@ -164,7 +174,13 @@ endmodule
// SiliconBlue Logic Cells
(* abc9_lut=1, lib_whitebox *)
-module SB_LUT4 (output O, input I0, I1, I2, I3);
+module SB_LUT4 (
+ output O,
+ input I0 `ICE40_DEFAULT_ASSIGNMENT_0,
+ input I1 `ICE40_DEFAULT_ASSIGNMENT_0,
+ input I2 `ICE40_DEFAULT_ASSIGNMENT_0,
+ input I3 `ICE40_DEFAULT_ASSIGNMENT_0
+);
parameter [15:0] LUT_INIT = 0;
wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0];
wire [3:0] s2 = I2 ? s3[ 7:4] : s3[3:0];
@@ -172,37 +188,37 @@ module SB_LUT4 (output O, input I0, I1, I2, I3);
assign O = I0 ? s1[1] : s1[0];
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L80
(I0 => O) = (449, 386);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L83
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L83
(I1 => O) = (400, 379);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L86
(I2 => O) = (379, 351);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L88
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L88
(I3 => O) = (316, 288);
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L80
(I0 => O) = (662, 569);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L83
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L83
(I1 => O) = (589, 558);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L86
(I2 => O) = (558, 517);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L88
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L88
(I3 => O) = (465, 423);
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L92
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L92
(I0 => O) = (1245, 1285);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L95
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L95
(I1 => O) = (1179, 1232);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L98
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L98
(I2 => O) = (1179, 1205);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L100
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L100
(I3 => O) = (861, 874);
endspecify
`endif
@@ -213,32 +229,32 @@ module SB_CARRY (output CO, input I0, I1, CI);
assign CO = (I0 && I1) || ((I0 || I1) && CI);
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L79
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L79
(CI => CO) = (126, 105);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L82
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L82
(I0 => CO) = (259, 245);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L85
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_hx1k.txt#L85
(I1 => CO) = (231, 133);
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L79
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L79
(CI => CO) = (186, 155);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L82
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L82
(I0 => CO) = (382, 362);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L85
- (I0 => CO) = (341, 196);
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_lp1k.txt#L85
+ (I1 => CO) = (341, 196);
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L91
(CI => CO) = (278, 278);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L94
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L94
(I0 => CO) = (675, 662);
- // https://github.com/cliffordwolf/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L97
- (I0 => CO) = (609, 358);
+ // https://github.com/YosysHQ/icestorm/blob/be0bca0230d6fe1102e0a360b953fbb0d273a39f/icefuzz/timings_up5k.txt#L97
+ (I1 => CO) = (609, 358);
endspecify
`endif
endmodule
@@ -247,35 +263,37 @@ endmodule
(* abc9_flop, lib_whitebox *)
module SB_DFF (
- output `SB_DFF_REG,
+ output reg Q,
input C, D
);
+ `SB_DFF_INIT
+
always @(posedge C)
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, posedge C, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
(posedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
(posedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
(posedge C => (Q : D)) = 1391;
endspecify
`endif
@@ -283,42 +301,44 @@ endmodule
(* abc9_flop, lib_whitebox *)
module SB_DFFE (
- output `SB_DFF_REG,
- input C, E, D
+ output reg Q,
+ input C, E `ICE40_DEFAULT_ASSIGNMENT_1, D
);
+ `SB_DFF_INIT
+
always @(posedge C)
if (E)
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, posedge C &&& E, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if (E) (posedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C &&& E, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if (E) (posedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if (E) (posedge C => (Q : D)) = 1391;
endspecify
`endif
@@ -326,9 +346,11 @@ endmodule
(* abc9_flop, lib_whitebox *)
module SB_DFFSR (
- output `SB_DFF_REG,
+ output reg Q,
input C, R, D
);
+ `SB_DFF_INIT
+
always @(posedge C)
if (R)
Q <= 0;
@@ -336,36 +358,36 @@ module SB_DFFSR (
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, posedge C, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78
$setup(R, posedge C, 203);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if ( R) (posedge C => (Q : 1'b0)) = 540;
if (!R) (posedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
$setup(R, posedge C, 299);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if ( R) (posedge C => (Q : 1'b0)) = 796;
if (!R) (posedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
$setup(R, posedge C, 530);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if ( R) (posedge C => (Q : 1'b0)) = 1391;
if (!R) (posedge C => (Q : D)) = 1391;
endspecify
@@ -374,9 +396,11 @@ endmodule
(* abc9_box, lib_whitebox *)
module SB_DFFR (
- output `SB_DFF_REG,
+ output reg Q,
input C, R, D
);
+ `SB_DFF_INIT
+
always @(posedge C, posedge R)
if (R)
Q <= 0;
@@ -384,12 +408,12 @@ module SB_DFFR (
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, posedge C, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
$setup(negedge R, posedge C, 160);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
`ifndef YOSYS
(posedge R => (Q : 1'b0)) = 599;
`else
@@ -397,18 +421,18 @@ module SB_DFFR (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if (!R) (posedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
$setup(negedge R, posedge C, 235);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
`ifndef YOSYS
(posedge R => (Q : 1'b0)) = 883;
`else
@@ -416,18 +440,18 @@ module SB_DFFR (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if (!R) (posedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
$setup(negedge R, posedge C, 424);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
`ifndef YOSYS
(posedge R => (Q : 1'b0)) = 1589;
`else
@@ -435,7 +459,7 @@ module SB_DFFR (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if (!R) (posedge C => (Q : D)) = 1391;
endspecify
`endif
@@ -443,9 +467,11 @@ endmodule
(* abc9_flop, lib_whitebox *)
module SB_DFFSS (
- output `SB_DFF_REG,
+ output reg Q,
input C, S, D
);
+ `SB_DFF_INIT
+
always @(posedge C)
if (S)
Q <= 1;
@@ -453,36 +479,36 @@ module SB_DFFSS (
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, posedge C, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78
$setup(S, posedge C, 203);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if ( S) (posedge C => (Q : 1'b1)) = 540;
if (!S) (posedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
$setup(S, posedge C, 299);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if ( S) (posedge C => (Q : 1'b1)) = 796;
if (!S) (posedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
$setup(S, posedge C, 530);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if ( S) (posedge C => (Q : 1'b1)) = 1391;
if (!S) (posedge C => (Q : D)) = 1391;
endspecify
@@ -491,9 +517,11 @@ endmodule
(* abc9_box, lib_whitebox *)
module SB_DFFS (
- output `SB_DFF_REG,
+ output reg Q,
input C, S, D
);
+ `SB_DFF_INIT
+
always @(posedge C, posedge S)
if (S)
Q <= 1;
@@ -501,12 +529,12 @@ module SB_DFFS (
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, posedge C, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
$setup(negedge S, posedge C, 160);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
`ifndef YOSYS
(posedge S => (Q : 1'b1)) = 599;
`else
@@ -514,18 +542,18 @@ module SB_DFFS (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if (!S) (posedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
$setup(negedge S, posedge C, 235);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
`ifndef YOSYS
(posedge S => (Q : 1'b1)) = 883;
`else
@@ -533,18 +561,18 @@ module SB_DFFS (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if (!S) (posedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
$setup(negedge S, posedge C, 424);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
`ifndef YOSYS
(posedge S => (Q : 1'b1)) = 1589;
`else
@@ -552,7 +580,7 @@ module SB_DFFS (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if (!S) (posedge C => (Q : D)) = 1391;
endspecify
`endif
@@ -560,9 +588,11 @@ endmodule
(* abc9_flop, lib_whitebox *)
module SB_DFFESR (
- output `SB_DFF_REG,
- input C, E, R, D
+ output reg Q,
+ input C, E `ICE40_DEFAULT_ASSIGNMENT_1, R, D
);
+ `SB_DFF_INIT
+
always @(posedge C)
if (E) begin
if (R)
@@ -572,42 +602,42 @@ module SB_DFFESR (
end
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, posedge C &&& E && !R, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78
$setup(R, posedge C &&& E, 203);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if (E && R) (posedge C => (Q : 1'b0)) = 540;
if (E && !R) (posedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C &&& E && !R, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
$setup(R, posedge C &&& E, 299);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if (E && R) (posedge C => (Q : 1'b0)) = 796;
if (E && !R) (posedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
$setup(R, posedge C &&& E, 530);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if (E && R) (posedge C => (Q : 1'b0)) = 1391;
if (E && !R) (posedge C => (Q : D)) = 1391;
endspecify
@@ -616,9 +646,11 @@ endmodule
(* abc9_box, lib_whitebox *)
module SB_DFFER (
- output `SB_DFF_REG,
- input C, E, R, D
+ output reg Q,
+ input C, E `ICE40_DEFAULT_ASSIGNMENT_1, R, D
);
+ `SB_DFF_INIT
+
always @(posedge C, posedge R)
if (R)
Q <= 0;
@@ -626,14 +658,14 @@ module SB_DFFER (
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, posedge C &&& E, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
$setup(negedge R, posedge C, 160);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
`ifndef YOSYS
(posedge R => (Q : 1'b0)) = 599;
`else
@@ -641,20 +673,20 @@ module SB_DFFER (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if (E && !R) (posedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C &&& E, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
$setup(negedge R, posedge C, 235);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
`ifndef YOSYS
(posedge R => (Q : 1'b0)) = 883;
`else
@@ -662,20 +694,20 @@ module SB_DFFER (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if (E && !R) (posedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
$setup(negedge R, posedge C, 424);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
`ifndef YOSYS
(posedge R => (Q : 1'b0)) = 1589;
`else
@@ -683,7 +715,7 @@ module SB_DFFER (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if (E && !R) (posedge C => (Q : D)) = 1391;
endspecify
`endif
@@ -691,9 +723,11 @@ endmodule
(* abc9_flop, lib_whitebox *)
module SB_DFFESS (
- output `SB_DFF_REG,
- input C, E, S, D
+ output reg Q,
+ input C, E `ICE40_DEFAULT_ASSIGNMENT_1, S, D
);
+ `SB_DFF_INIT
+
always @(posedge C)
if (E) begin
if (S)
@@ -703,42 +737,42 @@ module SB_DFFESS (
end
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, posedge C &&& E && !S, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78
$setup(S, posedge C &&& E, 203);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if (E && S) (posedge C => (Q : 1'b1)) = 540;
if (E && !S) (posedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C &&& E && !S, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
$setup(S, posedge C &&& E, 299);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if (E && S) (posedge C => (Q : 1'b1)) = 796;
if (E && !S) (posedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
$setup(S, posedge C &&& E, 530);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if (E && S) (posedge C => (Q : 1'b1)) = 1391;
if (E && !S) (posedge C => (Q : D)) = 1391;
endspecify
@@ -747,9 +781,11 @@ endmodule
(* abc9_box, lib_whitebox *)
module SB_DFFES (
- output `SB_DFF_REG,
- input C, E, S, D
+ output reg Q,
+ input C, E `ICE40_DEFAULT_ASSIGNMENT_1, S, D
);
+ `SB_DFF_INIT
+
always @(posedge C, posedge S)
if (S)
Q <= 1;
@@ -757,14 +793,14 @@ module SB_DFFES (
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, posedge C &&& E, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
$setup(posedge S, posedge C, 160);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
`ifndef YOSYS
(posedge S => (Q : 1'b1)) = 599;
`else
@@ -772,20 +808,20 @@ module SB_DFFES (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if (E && !S) (posedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C &&& E, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
$setup(posedge S, posedge C, 235);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
`ifndef YOSYS
(posedge S => (Q : 1'b1)) = 883;
`else
@@ -793,20 +829,20 @@ module SB_DFFES (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if (E && !S) (posedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, posedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
$setup(E, posedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
$setup(posedge S, posedge C, 424);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
`ifndef YOSYS
(posedge S => (Q : 1'b1)) = 1589;
`else
@@ -814,7 +850,7 @@ module SB_DFFES (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if (E && !S) (posedge C => (Q : D)) = 1391;
endspecify
`endif
@@ -824,35 +860,37 @@ endmodule
(* abc9_flop, lib_whitebox *)
module SB_DFFN (
- output `SB_DFF_REG,
+ output reg Q,
input C, D
);
+ `SB_DFF_INIT
+
always @(negedge C)
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, negedge C, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
(negedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
(negedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
(negedge C => (Q : D)) = 1391;
endspecify
`endif
@@ -860,42 +898,44 @@ endmodule
(* abc9_flop, lib_whitebox *)
module SB_DFFNE (
- output `SB_DFF_REG,
- input C, E, D
+ output reg Q,
+ input C, E `ICE40_DEFAULT_ASSIGNMENT_1, D
);
+ `SB_DFF_INIT
+
always @(negedge C)
if (E)
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, negedge C &&& E, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if (E) (negedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C &&& E, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if (E) (negedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if (E) (negedge C => (Q : D)) = 1391;
endspecify
`endif
@@ -903,9 +943,11 @@ endmodule
(* abc9_flop, lib_whitebox *)
module SB_DFFNSR (
- output `SB_DFF_REG,
+ output reg Q,
input C, R, D
);
+ `SB_DFF_INIT
+
always @(negedge C)
if (R)
Q <= 0;
@@ -913,36 +955,36 @@ module SB_DFFNSR (
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, negedge C, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
$setup(R, negedge C, 203);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if ( R) (negedge C => (Q : 1'b0)) = 540;
if (!R) (negedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
$setup(R, negedge C, 299);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if ( R) (negedge C => (Q : 1'b0)) = 796;
if (!R) (negedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
$setup(R, negedge C, 530);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if ( R) (negedge C => (Q : 1'b0)) = 1391;
if (!R) (negedge C => (Q : D)) = 1391;
endspecify
@@ -951,9 +993,11 @@ endmodule
(* abc9_flop, lib_whitebox *)
module SB_DFFNR (
- output `SB_DFF_REG,
+ output reg Q,
input C, R, D
);
+ `SB_DFF_INIT
+
always @(negedge C, posedge R)
if (R)
Q <= 0;
@@ -961,12 +1005,12 @@ module SB_DFFNR (
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, negedge C, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
$setup(negedge R, negedge C, 160);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
`ifndef YOSYS
(posedge R => (Q : 1'b0)) = 599;
`else
@@ -974,18 +1018,18 @@ module SB_DFFNR (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if (!R) (negedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
$setup(negedge R, negedge C, 235);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
`ifndef YOSYS
(posedge R => (Q : 1'b0)) = 883;
`else
@@ -993,18 +1037,18 @@ module SB_DFFNR (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if (!R) (negedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
$setup(negedge R, negedge C, 424);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
`ifndef YOSYS
(posedge R => (Q : 1'b0)) = 1589;
`else
@@ -1012,7 +1056,7 @@ module SB_DFFNR (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if (!R) (negedge C => (Q : D)) = 1391;
endspecify
`endif
@@ -1020,9 +1064,11 @@ endmodule
(* abc9_flop, lib_whitebox *)
module SB_DFFNSS (
- output `SB_DFF_REG,
+ output reg Q,
input C, S, D
);
+ `SB_DFF_INIT
+
always @(negedge C)
if (S)
Q <= 1;
@@ -1030,36 +1076,36 @@ module SB_DFFNSS (
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, negedge C, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
$setup(S, negedge C, 203);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if ( S) (negedge C => (Q : 1'b1)) = 540;
if (!S) (negedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
$setup(S, negedge C, 299);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if ( S) (negedge C => (Q : 1'b1)) = 796;
if (!S) (negedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
$setup(S, negedge C, 530);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if ( S) (negedge C => (Q : 1'b1)) = 1391;
if (!S) (negedge C => (Q : D)) = 1391;
endspecify
@@ -1068,9 +1114,11 @@ endmodule
(* abc9_box, lib_whitebox *)
module SB_DFFNS (
- output `SB_DFF_REG,
+ output reg Q,
input C, S, D
);
+ `SB_DFF_INIT
+
always @(negedge C, posedge S)
if (S)
Q <= 1;
@@ -1078,12 +1126,12 @@ module SB_DFFNS (
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, negedge C, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
$setup(negedge S, negedge C, 160);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
`ifndef YOSYS
(posedge S => (Q : 1'b1)) = 599;
`else
@@ -1091,18 +1139,18 @@ module SB_DFFNS (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if (!S) (negedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
$setup(negedge S, negedge C, 235);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
`ifndef YOSYS
(posedge S => (Q : 1'b1)) = 883;
`else
@@ -1110,18 +1158,18 @@ module SB_DFFNS (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if (!S) (negedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
$setup(negedge S, negedge C, 424);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
`ifndef YOSYS
(posedge S => (Q : 1'b1)) = 1589;
`else
@@ -1129,7 +1177,7 @@ module SB_DFFNS (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if (!S) (negedge C => (Q : D)) = 1391;
endspecify
`endif
@@ -1137,9 +1185,11 @@ endmodule
(* abc9_flop, lib_whitebox *)
module SB_DFFNESR (
- output `SB_DFF_REG,
- input C, E, R, D
+ output reg Q,
+ input C, E `ICE40_DEFAULT_ASSIGNMENT_1, R, D
);
+ `SB_DFF_INIT
+
always @(negedge C)
if (E) begin
if (R)
@@ -1149,42 +1199,42 @@ module SB_DFFNESR (
end
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, negedge C &&& E && !R, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78
$setup(R, negedge C &&& E, 203);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if (E && R) (negedge C => (Q : 1'b0)) = 540;
if (E && !R) (negedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C &&& E && !R, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
$setup(R, negedge C &&& E, 299);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if (E && R) (negedge C => (Q : 1'b0)) = 796;
if (E && !R) (negedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
$setup(R, negedge C &&& E, 530);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if (E && R) (negedge C => (Q : 1'b0)) = 1391;
if (E && !R) (negedge C => (Q : D)) = 1391;
endspecify
@@ -1193,9 +1243,11 @@ endmodule
(* abc9_box, lib_whitebox *)
module SB_DFFNER (
- output `SB_DFF_REG,
- input C, E, R, D
+ output reg Q,
+ input C, E `ICE40_DEFAULT_ASSIGNMENT_1, R, D
);
+ `SB_DFF_INIT
+
always @(negedge C, posedge R)
if (R)
Q <= 0;
@@ -1203,14 +1255,14 @@ module SB_DFFNER (
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, negedge C &&& E, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
$setup(R, negedge C, 2160);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
`ifndef YOSYS
(posedge R => (Q : 1'b0)) = 599;
`else
@@ -1218,20 +1270,20 @@ module SB_DFFNER (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if (E && !R) (negedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C &&& E, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
$setup(R, negedge C, 235);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
`ifndef YOSYS
(posedge R => (Q : 1'b0)) = 883;
`else
@@ -1239,20 +1291,20 @@ module SB_DFFNER (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if (E && !R) (negedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
$setup(negedge R, negedge C, 424);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
`ifndef YOSYS
(posedge R => (Q : 1'b0)) = 1589;
`else
@@ -1260,7 +1312,7 @@ module SB_DFFNER (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if (E && !R) (negedge C => (Q : D)) = 1391;
endspecify
`endif
@@ -1268,9 +1320,11 @@ endmodule
(* abc9_flop, lib_whitebox *)
module SB_DFFNESS (
- output `SB_DFF_REG,
- input C, E, S, D
+ output reg Q,
+ input C, E `ICE40_DEFAULT_ASSIGNMENT_1, S, D
);
+ `SB_DFF_INIT
+
always @(negedge C)
if (E) begin
if (S)
@@ -1280,42 +1334,42 @@ module SB_DFFNESS (
end
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, negedge C &&& E && !S, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78
$setup(S, negedge C &&& E, 203);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if (E && S) (negedge C => (Q : 1'b1)) = 540;
if (E && !S) (negedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C &&& E && !S, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
$setup(S, negedge C &&& E, 299);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if (E && S) (negedge C => (Q : 1'b1)) = 796;
if (E && !S) (negedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
$setup(S, negedge C &&& E, 530);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if (E && S) (negedge C => (Q : 1'b1)) = 1391;
if (E && !S) (negedge C => (Q : D)) = 1391;
endspecify
@@ -1324,9 +1378,11 @@ endmodule
(* abc9_box, lib_whitebox *)
module SB_DFFNES (
- output `SB_DFF_REG,
- input C, E, S, D
+ output reg Q,
+ input C, E `ICE40_DEFAULT_ASSIGNMENT_1, S, D
);
+ `SB_DFF_INIT
+
always @(negedge C, posedge S)
if (S)
Q <= 1;
@@ -1334,14 +1390,14 @@ module SB_DFFNES (
Q <= D;
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
$setup(D, negedge C &&& E, 470 - 449);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L63
$setup(negedge S, negedge C, 160);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91
`ifndef YOSYS
(posedge S => (Q : 1'b1)) = 599;
`else
@@ -1350,20 +1406,20 @@ module SB_DFFNES (
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
if (E && !S) (negedge C => (Q : D)) = 540;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C &&& E, 693 - 662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L63
$setup(negedge S, negedge C, 235);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91
`ifndef YOSYS
(posedge S => (Q : 1'b1)) = 883;
`else
@@ -1371,20 +1427,20 @@ module SB_DFFNES (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
if (E && !S) (negedge C => (Q : D)) = 796;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
- // minus https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // minus https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
$setup(D, negedge C &&& E, /*1232 - 1285*/ 0); // Negative times not currently supported
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
$setup(E, negedge C, 0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L75
$setup(negedge S, negedge C, 424);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103
`ifndef YOSYS
(posedge S => (Q : 1'b1)) = 1589;
`else
@@ -1392,7 +1448,7 @@ module SB_DFFNES (
// but for facilitating a bypass box, let's pretend it's
// a simple path
`endif
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
if (E && !S) (negedge C => (Q : D)) = 1391;
endspecify
`endif
@@ -1402,11 +1458,16 @@ endmodule
module SB_RAM40_4K (
output [15:0] RDATA,
- input RCLK, RCLKE, RE,
+ input RCLK,
+ input RCLKE `ICE40_DEFAULT_ASSIGNMENT_1,
+ input RE `ICE40_DEFAULT_ASSIGNMENT_0,
input [10:0] RADDR,
- input WCLK, WCLKE, WE,
+ input WCLK,
+ input WCLKE `ICE40_DEFAULT_ASSIGNMENT_1,
+ input WE `ICE40_DEFAULT_ASSIGNMENT_0,
input [10:0] WADDR,
- input [15:0] MASK, WDATA
+ input [15:0] MASK `ICE40_DEFAULT_ASSIGNMENT_V(16'h 0000),
+ input [15:0] WDATA
);
// MODE 0: 256 x 16
// MODE 1: 512 x 8
@@ -1568,67 +1629,67 @@ module SB_RAM40_4K (
`endif
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L343-L358
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L343-L358
$setup(MASK, posedge WCLK &&& WE && WCLKE, 274);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L359-L369
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L359-L369
$setup(RADDR, posedge RCLK &&& RE && RCLKE, 203);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L370
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L370
$setup(RCLKE, posedge RCLK, 267);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L371
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L371
$setup(RE, posedge RCLK, 98);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L372-L382
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L372-L382
$setup(WADDR, posedge WCLK &&& WE && WCLKE, 224);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L383
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L383
$setup(WCLKE, posedge WCLK, 267);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L384-L399
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L384-L399
$setup(WDATA, posedge WCLK &&& WE && WCLKE, 161);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L400
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L400
$setup(WE, posedge WCLK, 133);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
(posedge RCLK => (RDATA : 16'bx)) = 2146;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L343-L358
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L343-L358
$setup(MASK, posedge WCLK &&& WE && WCLKE, 403);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L359-L369
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L359-L369
$setup(RADDR, posedge RCLK &&& RE && RCLKE, 300);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L370
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L370
$setup(RCLKE, posedge RCLK, 393);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L371
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L371
$setup(RE, posedge RCLK, 145);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L372-L382
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L372-L382
$setup(WADDR, posedge WCLK &&& WE && WCLKE, 331);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L383
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L383
$setup(WCLKE, posedge WCLK, 393);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L384-L399
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L384-L399
$setup(WDATA, posedge WCLK &&& WE && WCLKE, 238);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L400
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L400
$setup(WE, posedge WCLK, 196);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
(posedge RCLK => (RDATA : 16'bx)) = 3163;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12968-12983
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12968-12983
$setup(MASK, posedge WCLK &&& WE && WCLKE, 517);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12984-12994
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12984-12994
$setup(RADDR, posedge RCLK &&& RE && RCLKE, 384);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12995
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12995
$setup(RCLKE, posedge RCLK, 503);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12996
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12996
$setup(RE, posedge RCLK, 185);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12997-13007
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12997-13007
$setup(WADDR, posedge WCLK &&& WE && WCLKE, 424);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13008
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13008
$setup(WCLKE, posedge WCLK, 503);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13009-13024
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13009-13024
$setup(WDATA, posedge WCLK &&& WE && WCLKE, 305);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13025
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13025
$setup(WE, posedge WCLK, 252);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
(posedge RCLK => (RDATA : 16'bx)) = 1179;
endspecify
`endif
@@ -1636,11 +1697,16 @@ endmodule
module SB_RAM40_4KNR (
output [15:0] RDATA,
- input RCLKN, RCLKE, RE,
+ input RCLKN,
+ input RCLKE `ICE40_DEFAULT_ASSIGNMENT_1,
+ input RE `ICE40_DEFAULT_ASSIGNMENT_0,
input [10:0] RADDR,
- input WCLK, WCLKE, WE,
+ input WCLK,
+ input WCLKE `ICE40_DEFAULT_ASSIGNMENT_1,
+ input WE `ICE40_DEFAULT_ASSIGNMENT_0,
input [10:0] WADDR,
- input [15:0] MASK, WDATA
+ input [15:0] MASK `ICE40_DEFAULT_ASSIGNMENT_V(16'h 0000),
+ input [15:0] WDATA
);
parameter WRITE_MODE = 0;
parameter READ_MODE = 0;
@@ -1699,67 +1765,67 @@ module SB_RAM40_4KNR (
);
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L343-L358
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L343-L358
$setup(MASK, posedge WCLK &&& WE && WCLKE, 274);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L359-L369
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L359-L369
$setup(RADDR, posedge RCLKN &&& RE && RCLKE, 203);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L370
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L370
$setup(RCLKE, posedge RCLKN, 267);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L371
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L371
$setup(RE, posedge RCLKN, 98);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L372-L382
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L372-L382
$setup(WADDR, posedge WCLK &&& WE && WCLKE, 224);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L383
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L383
$setup(WCLKE, posedge WCLK, 267);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L384-L399
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L384-L399
$setup(WDATA, posedge WCLK &&& WE && WCLKE, 161);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L400
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L400
$setup(WE, posedge WCLK, 133);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
(posedge RCLKN => (RDATA : 16'bx)) = 2146;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L343-L358
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L343-L358
$setup(MASK, posedge WCLK &&& WE && WCLKE, 403);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L359-L369
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L359-L369
$setup(RADDR, posedge RCLKN &&& RE && RCLKE, 300);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L370
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L370
$setup(RCLKE, posedge RCLKN, 393);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L371
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L371
$setup(RE, posedge RCLKN, 145);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L372-L382
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L372-L382
$setup(WADDR, posedge WCLK &&& WE && WCLKE, 331);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L383
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L383
$setup(WCLKE, posedge WCLK, 393);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L384-L399
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L384-L399
$setup(WDATA, posedge WCLK &&& WE && WCLKE, 238);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L400
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L400
$setup(WE, posedge WCLK, 196);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
(posedge RCLKN => (RDATA : 16'bx)) = 3163;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12968-12983
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12968-12983
$setup(MASK, posedge WCLK &&& WE && WCLKE, 517);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12984-12994
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12984-12994
$setup(RADDR, posedge RCLKN &&& RE && RCLKE, 384);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12995
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12995
$setup(RCLKE, posedge RCLKN, 503);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12996
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12996
$setup(RE, posedge RCLKN, 185);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12997-13007
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12997-13007
$setup(WADDR, posedge WCLK &&& WE && WCLKE, 424);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13008
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13008
$setup(WCLKE, posedge WCLK, 503);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13009-13024
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13009-13024
$setup(WDATA, posedge WCLK &&& WE && WCLKE, 305);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13025
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13025
$setup(WE, posedge WCLK, 252);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
(posedge RCLKN => (RDATA : 16'bx)) = 1179;
endspecify
`endif
@@ -1767,11 +1833,16 @@ endmodule
module SB_RAM40_4KNW (
output [15:0] RDATA,
- input RCLK, RCLKE, RE,
+ input RCLK,
+ input RCLKE `ICE40_DEFAULT_ASSIGNMENT_1,
+ input RE `ICE40_DEFAULT_ASSIGNMENT_0,
input [10:0] RADDR,
- input WCLKN, WCLKE, WE,
+ input WCLKN,
+ input WCLKE `ICE40_DEFAULT_ASSIGNMENT_1,
+ input WE `ICE40_DEFAULT_ASSIGNMENT_0,
input [10:0] WADDR,
- input [15:0] MASK, WDATA
+ input [15:0] MASK `ICE40_DEFAULT_ASSIGNMENT_V(16'h 0000),
+ input [15:0] WDATA
);
parameter WRITE_MODE = 0;
parameter READ_MODE = 0;
@@ -1830,67 +1901,67 @@ module SB_RAM40_4KNW (
);
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L343-L358
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L343-L358
$setup(MASK, posedge WCLKN &&& WE && WCLKE, 274);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L359-L369
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L359-L369
$setup(RADDR, posedge RCLK &&& RE && RCLKE, 203);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L370
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L370
$setup(RCLKE, posedge RCLK, 267);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L371
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L371
$setup(RE, posedge RCLK, 98);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L372-L382
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L372-L382
$setup(WADDR, posedge WCLKN &&& WE && WCLKE, 224);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L383
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L383
$setup(WCLKE, posedge WCLKN, 267);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L384-L399
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L384-L399
$setup(WDATA, posedge WCLKN &&& WE && WCLKE, 161);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L400
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L400
$setup(WE, posedge WCLKN, 133);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
(posedge RCLK => (RDATA : 16'bx)) = 2146;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L343-L358
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L343-L358
$setup(MASK, posedge WCLKN &&& WE && WCLKE, 403);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L359-L369
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L359-L369
$setup(RADDR, posedge RCLK &&& RE && RCLKE, 300);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L370
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L370
$setup(RCLKE, posedge RCLK, 393);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L371
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L371
$setup(RE, posedge RCLK, 145);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L372-L382
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L372-L382
$setup(WADDR, posedge WCLKN &&& WE && WCLKE, 331);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L383
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L383
$setup(WCLKE, posedge WCLKN, 393);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L384-L399
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L384-L399
$setup(WDATA, posedge WCLKN &&& WE && WCLKE, 238);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L400
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L400
$setup(WE, posedge WCLKN, 196);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
(posedge RCLK => (RDATA : 16'bx)) = 3163;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12968-12983
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12968-12983
$setup(MASK, posedge WCLKN &&& WE && WCLKE, 517);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12984-12994
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12984-12994
$setup(RADDR, posedge RCLK &&& RE && RCLKE, 384);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12995
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12995
$setup(RCLKE, posedge RCLK, 503);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12996
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12996
$setup(RE, posedge RCLK, 185);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12997-13007
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12997-13007
$setup(WADDR, posedge WCLKN &&& WE && WCLKE, 424);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13008
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13008
$setup(WCLKE, posedge WCLKN, 503);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13009-13024
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13009-13024
$setup(WDATA, posedge WCLKN &&& WE && WCLKE, 305);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13025
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13025
$setup(WE, posedge WCLKN, 252);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
(posedge RCLK => (RDATA : 16'bx)) = 1179;
endspecify
`endif
@@ -1898,11 +1969,16 @@ endmodule
module SB_RAM40_4KNRNW (
output [15:0] RDATA,
- input RCLKN, RCLKE, RE,
+ input RCLKN,
+ input RCLKE `ICE40_DEFAULT_ASSIGNMENT_1,
+ input RE `ICE40_DEFAULT_ASSIGNMENT_0,
input [10:0] RADDR,
- input WCLKN, WCLKE, WE,
+ input WCLKN,
+ input WCLKE `ICE40_DEFAULT_ASSIGNMENT_1,
+ input WE `ICE40_DEFAULT_ASSIGNMENT_0,
input [10:0] WADDR,
- input [15:0] MASK, WDATA
+ input [15:0] MASK `ICE40_DEFAULT_ASSIGNMENT_V(16'h 0000),
+ input [15:0] WDATA
);
parameter WRITE_MODE = 0;
parameter READ_MODE = 0;
@@ -1961,67 +2037,67 @@ module SB_RAM40_4KNRNW (
);
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L343-L358
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L343-L358
$setup(MASK, posedge WCLKN &&& WE && WCLKE, 274);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L359-L369
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L359-L369
$setup(RADDR, posedge RCLKN &&& RE && RCLKE, 203);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L370
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L370
$setup(RCLKE, posedge RCLKN, 267);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L371
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L371
$setup(RE, posedge RCLKN, 98);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L372-L382
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L372-L382
$setup(WADDR, posedge WCLKN &&& WE && WCLKE, 224);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L383
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L383
$setup(WCLKE, posedge WCLKN, 267);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L384-L399
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L384-L399
$setup(WDATA, posedge WCLKN &&& WE && WCLKE, 161);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L400
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L400
$setup(WE, posedge WCLKN, 133);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L401
(posedge RCLKN => (RDATA : 16'bx)) = 2146;
endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L343-L358
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L343-L358
$setup(MASK, posedge WCLKN &&& WE && WCLKE, 403);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L359-L369
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L359-L369
$setup(RADDR, posedge RCLKN &&& RE && RCLKE, 300);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L370
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L370
$setup(RCLKE, posedge RCLKN, 393);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L371
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L371
$setup(RE, posedge RCLKN, 145);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L372-L382
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L372-L382
$setup(WADDR, posedge WCLKN &&& WE && WCLKE, 331);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L383
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L383
$setup(WCLKE, posedge WCLKN, 393);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L384-L399
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L384-L399
$setup(WDATA, posedge WCLKN &&& WE && WCLKE, 238);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L400
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L400
$setup(WE, posedge WCLKN, 196);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L401
(posedge RCLKN => (RDATA : 16'bx)) = 3163;
endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12968-12983
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12968-12983
$setup(MASK, posedge WCLKN &&& WE && WCLKE, 517);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12984-12994
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12984-12994
$setup(RADDR, posedge RCLKN &&& RE && RCLKE, 384);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12995
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12995
$setup(RCLKE, posedge RCLKN, 503);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12996
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12996
$setup(RE, posedge RCLKN, 185);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12997-13007
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L12997-13007
$setup(WADDR, posedge WCLKN &&& WE && WCLKE, 424);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13008
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13008
$setup(WCLKE, posedge WCLKN, 503);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13009-13024
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13009-13024
$setup(WDATA, posedge WCLKN &&& WE && WCLKE, 305);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13025
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13025
$setup(WE, posedge WCLKN, 252);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13026
(posedge RCLKN => (RDATA : 16'bx)) = 1179;
endspecify
`endif
@@ -2123,63 +2199,63 @@ endspecify
`endif
`ifdef ICE40_HX
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L79
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L79
(CIN => COUT) = (101:112:126, 85:94:105);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L80
(I0 => O) = (361:399:449, 310:343:386);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L81
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L81
(I0 => LO) = (293:324:365, 310:343:386);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L82
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L82
(I1 => COUT) = (209:231:259, 197:218:245);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L83
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L83
(I1 => O) = (321:355:400, 304:337:379);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L84
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L84
(I1 => LO) = (259:287:323, 304:337:379);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L85
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L85
(I2 => COUT) = (186:206:231, 107:118:133);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L86
(I2 => O) = (304:337:379, 282:312:351);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L87
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L87
(I2 => LO) = (254:281:316, 231:256:288);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L88
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L88
(I3 => O) = (254:281:316, 231:256:288);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L89
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L89
(I3 => LO) = (214:237:267, 220:243:274);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L90
(posedge CLK => (O : 1'bx)) = (434:480:540, 434:480:540);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91-L92
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L91-L92
(SR => O) = (482:535:599, 482:533:599);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L74
$setuphold(posedge CLK, posedge I0, 378:418:470, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L68
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L68
$setuphold(posedge CLK, negedge I0, 321:355:400, 0:0:0);
$setuphold(negedge CLK, posedge I0, 378:418:470, 0:0:0);
$setuphold(negedge CLK, negedge I0, 321:355:400, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L75
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L75
$setuphold(posedge CLK, posedge I1, 321:355:400, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L69
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L69
$setuphold(posedge CLK, negedge I1, 304:337:379, 0:0:0);
$setuphold(negedge CLK, posedge I1, 321:355:400, 0:0:0);
$setuphold(negedge CLK, negedge I1, 304:337:379, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L76
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L76
$setuphold(posedge CLK, posedge I2, 299:330:372, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L70
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L70
$setuphold(posedge CLK, negedge I2, 259:287:323, 0:0:0);
$setuphold(negedge CLK, posedge I2, 299:330:372, 0:0:0);
$setuphold(negedge CLK, negedge I2, 259:287:323, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L77
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L77
$setuphold(posedge CLK, posedge I3, 220:243:274, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L71
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L71
$setuphold(posedge CLK, negedge I3, 175:183:217, 0:0:0);
$setuphold(negedge CLK, posedge I3, 220:243:274, 0:0:0);
$setuphold(negedge CLK, negedge I3, 175:183:217, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L73
$setuphold(posedge CLK, negedge CEN, 0:0:0, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L67
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L67
$setuphold(posedge CLK, posedge CEN, 0:0:0, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L78
$setuphold(posedge CLK, posedge SR, 163:181:203, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L72
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_hx1k.txt#L72
$setuphold(posedge CLK, negedge SR, 113:125:140, 0:0:0);
$setuphold(negedge CLK, posedge SR, 163:181:203, 0:0:0);
$setuphold(negedge CLK, negedge SR, 113:125:140, 0:0:0);
@@ -2187,63 +2263,63 @@ endspecify
`endif
`ifdef ICE40_LP
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L79
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L79
(CIN => COUT) = (118:153:186, 98:128:155);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L80
(I0 => O) = (419:545:662, 360:468:569);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L81
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L81
(I0 => LO) = (340:442:538, 360:468:569);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L82
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L82
(I1 => COUT) = (242:315:382, 229:298:362);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L83
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L83
(I1 => O) = (372:485:589, 353:459:558);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L84
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L84
(I1 => LO) = (301:391:475, 353:459:558);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L85
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L85
(I2 => COUT) = (216:281:341, 124:162:196);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L86
(I2 => O) = (353:459:558, 327:425:517);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L87
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L87
(I2 => LO) = (288:374:455, 321:417:507);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L88
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L88
(I3 => O) = (294:383:465, 268:349:424);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L89
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L89
(I3 => LO) = (249:323:393, 255:332:403);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L90
(posedge CLK => (O : 1'bx)) = (504:655:796, 504:655:796);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91-L92
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L91-L92
(SR => O) = (559:726:883, 559:726:883);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L74
$setuphold(posedge CLK, posedge I0, 438:570:693, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L68
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L68
$setuphold(posedge CLK, negedge I0, 373:485:589, 0:0:0);
$setuphold(negedge CLK, posedge I0, 438:570:693, 0:0:0);
$setuphold(negedge CLK, negedge I0, 373:485:589, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L75
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L75
$setuphold(posedge CLK, posedge I1, 373:485:589, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L69
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L69
$setuphold(posedge CLK, negedge I1, 353:459:558, 0:0:0);
$setuphold(negedge CLK, posedge I1, 373:485:589, 0:0:0);
$setuphold(negedge CLK, negedge I1, 353:459:558, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L76
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L76
$setuphold(posedge CLK, posedge I2, 347:451:548, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L70
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L70
$setuphold(posedge CLK, negedge I2, 301:391:475, 0:0:0);
$setuphold(negedge CLK, posedge I2, 347:451:548, 0:0:0);
$setuphold(negedge CLK, negedge I2, 301:391:475, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L77
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L77
$setuphold(posedge CLK, posedge I3, 255:332:403, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L71
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L71
$setuphold(posedge CLK, negedge I3, 203:264:320, 0:0:0);
$setuphold(negedge CLK, posedge I3, 255:332:403, 0:0:0);
$setuphold(negedge CLK, negedge I3, 203:264:320, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L73
$setuphold(posedge CLK, negedge CEN, 0:0:0, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L67
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L67
$setuphold(posedge CLK, posedge CEN, 0:0:0, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L78
$setuphold(posedge CLK, posedge SR, 190:247:300, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L72
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_lp1k.txt#L72
$setuphold(posedge CLK, negedge SR, 131:170:207, 0:0:0);
$setuphold(negedge CLK, posedge SR, 190:247:300, 0:0:0);
$setuphold(negedge CLK, negedge SR, 131:170:207, 0:0:0);
@@ -2251,63 +2327,63 @@ endspecify
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L91
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L91
(CIN => COUT) = (103:181:278, 103:181:278);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L92
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L92
(I0 => O) = (462:808:1255, 477:834:1285);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L93
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L93
(I0 => LO) = (315:550:848, 334:585:901);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L94
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L94
(I1 => COUT) = (251:438:675, 246:430:662);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L95
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L95
(I1 => O) = (438:765:1179, 457:799:1232);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L96
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L96
(I1 => LO) = (275:481:742, 329:576:887);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L97
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L97
(I2 => COUT) = (226:395:609, 133:232:358);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L98
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L98
(I2 => O) = (438:765:1179, 447:782:1205);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L99
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L99
(I2 => LO) = (261:456:702, 290:507:781);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L100
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L100
(I3 => O) = (320:559:861, 226:370:874);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L101
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L101
(I3 => LO) = (216:378:583, 226:395:609);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L102
(posedge CLK => (O : 1'bx)) = (516:903:1391, 516:903:1391);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103-104
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L103-104
(SR => O) = (420:734:1131, 590:1032:1589);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L86
$setuphold(posedge CLK, posedge I0, 457:799:1232, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L80
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L80
$setuphold(posedge CLK, negedge I0, 393:688:1060, 0:0:0);
$setuphold(negedge CLK, posedge I0, 457:799:1232, 0:0:0);
$setuphold(negedge CLK, negedge I0, 393:688:1060, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L87
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L87
$setuphold(posedge CLK, posedge I1, 393:688:1060, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L81
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L81
$setuphold(posedge CLK, negedge I1, 373:653:1007, 0:0:0);
$setuphold(negedge CLK, posedge I1, 393:688:1060, 0:0:0);
$setuphold(negedge CLK, negedge I1, 373:653:1007, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L88
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L88
$setuphold(posedge CLK, posedge I2, 364:636:980, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L82
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L82
$setuphold(posedge CLK, negedge I2, 320:559:861, 0:0:0);
$setuphold(negedge CLK, posedge I2, 364:636:980, 0:0:0);
$setuphold(negedge CLK, negedge I2, 320:559:861, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L89
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L89
$setuphold(posedge CLK, posedge I3, 279:473:728, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L83
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L83
$setuphold(posedge CLK, negedge I3, 216:378:583, 0:0:0);
$setuphold(negedge CLK, posedge I3, 279:473:728, 0:0:0);
$setuphold(negedge CLK, negedge I3, 216:378:583, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L85
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L85
$setuphold(posedge CLK, negedge CEN, 0:0:0, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L79
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L79
$setuphold(posedge CLK, posedge CEN, 0:0:0, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L90
$setuphold(posedge CLK, posedge SR, 197:344:530, 0:0:0);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L84
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L84
$setuphold(posedge CLK, negedge SR, 143:249:384, 0:0:0);
$setuphold(negedge CLK, posedge SR, 197:344:530, 0:0:0);
$setuphold(negedge CLK, negedge SR, 131:170:207, 0:0:0);
@@ -2534,23 +2610,23 @@ module SB_SPRAM256KA (
`endif
`ifdef ICE40_U
specify
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13169-L13182
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13169-L13182
$setup(posedge ADDRESS, posedge CLOCK, 268);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13183
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13183
$setup(CHIPSELECT, posedge CLOCK, 404);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13184-L13199
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13184-L13199
$setup(DATAIN, posedge CLOCK, 143);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13200-L13203
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13200-L13203
$setup(MASKWREN, posedge CLOCK, 143);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13167
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13167
//$setup(negedge SLEEP, posedge CLOCK, 41505);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13167
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13167
//$setup(negedge STANDBY, posedge CLOCK, 1715);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13206
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13206
$setup(WREN, posedge CLOCK, 289);
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13207-L13222
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13207-L13222
(posedge CLOCK => (DATAOUT : 16'bx)) = 1821;
- // https://github.com/cliffordwolf/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13223-L13238
+ // https://github.com/YosysHQ/icestorm/blob/95949315364f8d9b0c693386aefadf44b28e2cf6/icefuzz/timings_up5k.txt#L13223-L13238
(posedge SLEEP => (DATAOUT : 16'b0)) = 1099;
endspecify
`endif
diff --git a/techlibs/ice40/ice40_braminit.cc b/techlibs/ice40/ice40_braminit.cc
index e5d1f7e24..955860740 100644
--- a/techlibs/ice40/ice40_braminit.cc
+++ b/techlibs/ice40/ice40_braminit.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc
index d28607904..b13d33018 100644
--- a/techlibs/ice40/ice40_opt.cc
+++ b/techlibs/ice40/ice40_opt.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc
index b945889fe..421ec3b4e 100644
--- a/techlibs/ice40/synth_ice40.cc
+++ b/techlibs/ice40/synth_ice40.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -399,7 +399,7 @@ struct SynthIce40Pass : public ScriptPass
run("ice40_wrapcarry -unwrap");
run("techmap -map +/ice40/ff_map.v");
run("clean");
- run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0");
+ run("opt_lut -dlogic SB_CARRY:I0=1:I1=2:CI=3 -dlogic SB_CARRY:CO=3");
}
if (check_label("map_cells"))
@@ -417,6 +417,7 @@ struct SynthIce40Pass : public ScriptPass
run("hierarchy -check");
run("stat");
run("check -noinit");
+ run("blackbox =A:whitebox");
}
if (check_label("blif"))
diff --git a/techlibs/intel/common/altpll_bb.v b/techlibs/intel/common/altpll_bb.v
index d2e6a3643..d649e06c6 100644
--- a/techlibs/intel/common/altpll_bb.v
+++ b/techlibs/intel/common/altpll_bb.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/intel/common/m9k_bb.v b/techlibs/intel/common/m9k_bb.v
index 4bb230642..551d5cc0c 100644
--- a/techlibs/intel/common/m9k_bb.v
+++ b/techlibs/intel/common/m9k_bb.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/intel/cyclone10lp/cells_arith.v b/techlibs/intel/cyclone10lp/cells_arith.v
index d8c46e865..d0d988145 100644
--- a/techlibs/intel/cyclone10lp/cells_arith.v
+++ b/techlibs/intel/cyclone10lp/cells_arith.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/intel/cyclone10lp/cells_map.v b/techlibs/intel/cyclone10lp/cells_map.v
index 22907b144..1341793df 100644
--- a/techlibs/intel/cyclone10lp/cells_map.v
+++ b/techlibs/intel/cyclone10lp/cells_map.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/intel/cyclone10lp/cells_sim.v b/techlibs/intel/cyclone10lp/cells_sim.v
index f5a8aee2b..ab9958992 100644
--- a/techlibs/intel/cyclone10lp/cells_sim.v
+++ b/techlibs/intel/cyclone10lp/cells_sim.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/intel/cycloneiv/cells_arith.v b/techlibs/intel/cycloneiv/cells_arith.v
index f7bc3cd65..1241e89fe 100644
--- a/techlibs/intel/cycloneiv/cells_arith.v
+++ b/techlibs/intel/cycloneiv/cells_arith.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/intel/cycloneiv/cells_map.v b/techlibs/intel/cycloneiv/cells_map.v
index 41afd94be..59f50bddb 100644
--- a/techlibs/intel/cycloneiv/cells_map.v
+++ b/techlibs/intel/cycloneiv/cells_map.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/intel/cycloneiv/cells_sim.v b/techlibs/intel/cycloneiv/cells_sim.v
index 2af2ab990..f3c8fbe03 100644
--- a/techlibs/intel/cycloneiv/cells_sim.v
+++ b/techlibs/intel/cycloneiv/cells_sim.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/intel/cycloneive/arith_map.v b/techlibs/intel/cycloneive/arith_map.v
index a755e10db..f31baf1e1 100644
--- a/techlibs/intel/cycloneive/arith_map.v
+++ b/techlibs/intel/cycloneive/arith_map.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/intel/cycloneive/cells_map.v b/techlibs/intel/cycloneive/cells_map.v
index 6d7f36ec5..646530d16 100644
--- a/techlibs/intel/cycloneive/cells_map.v
+++ b/techlibs/intel/cycloneive/cells_map.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/intel/cycloneive/cells_sim.v b/techlibs/intel/cycloneive/cells_sim.v
index f17b86fdf..9f4cb9a2e 100644
--- a/techlibs/intel/cycloneive/cells_sim.v
+++ b/techlibs/intel/cycloneive/cells_sim.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/intel/max10/cells_arith.v b/techlibs/intel/max10/cells_arith.v
index 8529706a7..ac78ff660 100644
--- a/techlibs/intel/max10/cells_arith.v
+++ b/techlibs/intel/max10/cells_arith.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/intel/max10/cells_map.v b/techlibs/intel/max10/cells_map.v
index 8f198daef..6fefcd5d0 100644
--- a/techlibs/intel/max10/cells_map.v
+++ b/techlibs/intel/max10/cells_map.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/intel/max10/cells_sim.v b/techlibs/intel/max10/cells_sim.v
index 98673596b..7705fa27a 100644
--- a/techlibs/intel/max10/cells_sim.v
+++ b/techlibs/intel/max10/cells_sim.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc
index a513528f7..166c81843 100644
--- a/techlibs/intel/synth_intel.cc
+++ b/techlibs/intel/synth_intel.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -233,6 +233,7 @@ struct SynthIntelPass : public ScriptPass {
run("hierarchy -check");
run("stat");
run("check -noinit");
+ run("blackbox =A:whitebox");
}
if (check_label("vqm")) {
diff --git a/techlibs/intel_alm/Makefile.inc b/techlibs/intel_alm/Makefile.inc
index da88762c4..614d5802c 100644
--- a/techlibs/intel_alm/Makefile.inc
+++ b/techlibs/intel_alm/Makefile.inc
@@ -13,6 +13,7 @@ $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/df
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dsp_sim.v))
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dsp_map.v))
$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/mem_sim.v))
+$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/misc_sim.v))
$(eval $(call add_share_file,share/intel_alm/cyclonev,techlibs/intel_alm/cyclonev/cells_sim.v))
diff --git a/techlibs/intel_alm/common/alm_sim.v b/techlibs/intel_alm/common/alm_sim.v
index 906a95b0b..242f1003f 100644
--- a/techlibs/intel_alm/common/alm_sim.v
+++ b/techlibs/intel_alm/common/alm_sim.v
@@ -77,6 +77,14 @@
// SUMOUT 368 1342 1323 887 927 - 785 -
// CARRYOUT 71 1082 1062 866 813 - 1198 -
+// Arria V LUT output timings (picoseconds):
+//
+// CARRY A B C D E F G
+// COMBOUT - 387 375 316 317 - 76 319 (LUT6)
+// COMBOUT - 387 375 316 317 218 76 319 (LUT7)
+// SUMOUT 249 744 732 562 576 - 511 -
+// CARRYOUT 19 629 623 530 514 - 696 -
+
(* abc9_lut=2, lib_whitebox *)
module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q);
@@ -92,6 +100,16 @@ specify
(F => Q) = 97;
endspecify
`endif
+`ifdef arriav
+specify
+ (A => Q) = 387;
+ (B => Q) = 375;
+ (C => Q) = 316;
+ (D => Q) = 317;
+ (E => Q) = 319;
+ (F => Q) = 76;
+endspecify
+`endif
`ifdef cyclone10gx
specify
(A => Q) = 275;
@@ -122,6 +140,15 @@ specify
(E => Q) = 97;
endspecify
`endif
+`ifdef arriav
+specify
+ (A => Q) = 375;
+ (B => Q) = 316;
+ (C => Q) = 317;
+ (D => Q) = 319;
+ (E => Q) = 76;
+endspecify
+`endif
`ifdef cyclone10gx
specify
(A => Q) = 272;
@@ -150,6 +177,14 @@ specify
(D => Q) = 97;
endspecify
`endif
+`ifdef arriav
+specify
+ (A => Q) = 316;
+ (B => Q) = 317;
+ (C => Q) = 319;
+ (D => Q) = 76;
+endspecify
+`endif
`ifdef cyclone10gx
specify
(A => Q) = 175;
@@ -176,6 +211,13 @@ specify
(C => Q) = 97;
endspecify
`endif
+`ifdef arriav
+specify
+ (A => Q) = 316;
+ (B => Q) = 317;
+ (C => Q) = 76;
+endspecify
+`endif
`ifdef cyclone10gx
specify
(A => Q) = 165;
@@ -200,6 +242,12 @@ specify
(B => Q) = 97;
endspecify
`endif
+`ifdef arriav
+specify
+ (A => Q) = 316;
+ (B => Q) = 76;
+endspecify
+`endif
`ifdef cyclone10gx
specify
(A => Q) = 162;
@@ -220,6 +268,11 @@ specify
(A => Q) = 97;
endspecify
`endif
+`ifdef arriav
+specify
+ (A => Q) = 76;
+endspecify
+`endif
`ifdef cyclone10gx
specify
(A => Q) = 53;
@@ -230,8 +283,10 @@ assign Q = ~A;
endmodule
-(* abc9_box, lib_whitebox *)
-module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, (* abc9_carry *) input CI, output SO, (* abc9_carry *) output CO);
+// Despite the abc9_carry attributes, this doesn't seem to stop ABC9 adding illegal fanout to the carry chain that nextpnr cannot handle.
+// So we treat it as a total blackbox from ABC9's perspective for now.
+// (* abc9_box, lib_whitebox *)
+module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, /* (* abc9_carry *) */ input CI, output SO, /* (* abc9_carry *) */ output CO);
parameter LUT0 = 16'h0000;
parameter LUT1 = 16'h0000;
@@ -253,6 +308,23 @@ specify
(CI => CO) = 36; // Divided by 2 to account for there being two ALUT_ARITHs in an ALM)
endspecify
`endif
+`ifdef arriav
+specify
+ (A => SO) = 744;
+ (B => SO) = 732;
+ (C => SO) = 562;
+ (D0 => SO) = 576;
+ (D1 => SO) = 511;
+ (CI => SO) = 249;
+
+ (A => CO) = 629;
+ (B => CO) = 623;
+ (C => CO) = 530;
+ (D0 => CO) = 514;
+ (D1 => CO) = 696;
+ (CI => CO) = 10; // Divided by 2 to account for there being two ALUT_ARITHs in an ALM)
+endspecify
+`endif
`ifdef cyclone10gx
specify
(A => SO) = 644;
diff --git a/techlibs/intel_alm/common/arith_alm_map.v b/techlibs/intel_alm/common/arith_alm_map.v
index 8515eeb56..7cbf02e9c 100644
--- a/techlibs/intel_alm/common/arith_alm_map.v
+++ b/techlibs/intel_alm/common/arith_alm_map.v
@@ -34,7 +34,7 @@ wire [Y_WIDTH:0] ALM_CARRY;
// Start of carry chain
generate
- if (_TECHMAP_CONSTMSK_CI_ == 1) begin
+ if (_TECHMAP_CONSTMSK_CI_ == 1 && _TECHMAP_CONSTVAL_CI_ == 1'b0) begin
assign ALM_CARRY[0] = _TECHMAP_CONSTVAL_CI_;
end else begin
MISTRAL_ALUT_ARITH #(
diff --git a/techlibs/intel_alm/common/bram_m10k.txt b/techlibs/intel_alm/common/bram_m10k.txt
index e9355fe2c..0d9a49b7d 100644
--- a/techlibs/intel_alm/common/bram_m10k.txt
+++ b/techlibs/intel_alm/common/bram_m10k.txt
@@ -4,18 +4,12 @@ bram MISTRAL_M10K
dbits 1 @D8192x1
abits 12 @D4096x2
dbits 2 @D4096x2
- abits 11 @D2048x4 @D2048x5
- dbits 4 @D2048x4
+ abits 11 @D2048x5
dbits 5 @D2048x5
- abits 10 @D1024x8 @D1024x10
- dbits 8 @D1024x8
+ abits 10 @D1024x10
dbits 10 @D1024x10
- abits 9 @D512x16 @D512x20
- dbits 16 @D512x16
+ abits 9 @D512x20
dbits 20 @D512x20
- abits 8 @D256x32 @D256x40
- dbits 32 @D256x32
- dbits 40 @D256x40
groups 2
ports 1 1
wrmode 1 0
diff --git a/techlibs/intel_alm/common/bram_m20k_map.v b/techlibs/intel_alm/common/bram_m20k_map.v
index 92f41310f..15739d66a 100644
--- a/techlibs/intel_alm/common/bram_m20k_map.v
+++ b/techlibs/intel_alm/common/bram_m20k_map.v
@@ -1,31 +1,31 @@
-module __MISTRAL_M20K_SDP(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
-
-parameter CFG_ABITS = 10;
-parameter CFG_DBITS = 20;
-parameter CFG_ENABLE_A = 1;
-parameter CFG_ENABLE_B = 1;
-
-input CLK1;
-input [CFG_ABITS-1:0] A1ADDR, B1ADDR;
-input [CFG_DBITS-1:0] A1DATA;
-output [CFG_DBITS-1:0] B1DATA;
-input [CFG_ENABLE_A-1:0] A1EN, B1EN;
-
-altsyncram #(
- .operation_mode("dual_port"),
- .ram_block_type("m20k"),
- .widthad_a(CFG_ABITS),
- .width_a(CFG_DBITS),
- .widthad_b(CFG_ABITS),
- .width_b(CFG_DBITS),
-) _TECHMAP_REPLACE_ (
- .address_a(A1ADDR),
- .data_a(A1DATA),
- .wren_a(A1EN),
- .address_b(B1ADDR),
- .q_b(B1DATA),
- .clock0(CLK1),
- .clock1(CLK1)
-);
-
-endmodule
+module __MISTRAL_M20K_SDP(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+
+parameter CFG_ABITS = 10;
+parameter CFG_DBITS = 20;
+parameter CFG_ENABLE_A = 1;
+parameter CFG_ENABLE_B = 1;
+
+input CLK1;
+input [CFG_ABITS-1:0] A1ADDR, B1ADDR;
+input [CFG_DBITS-1:0] A1DATA;
+output [CFG_DBITS-1:0] B1DATA;
+input [CFG_ENABLE_A-1:0] A1EN, B1EN;
+
+altsyncram #(
+ .operation_mode("dual_port"),
+ .ram_block_type("m20k"),
+ .widthad_a(CFG_ABITS),
+ .width_a(CFG_DBITS),
+ .widthad_b(CFG_ABITS),
+ .width_b(CFG_DBITS),
+) _TECHMAP_REPLACE_ (
+ .address_a(A1ADDR),
+ .data_a(A1DATA),
+ .wren_a(A1EN),
+ .address_b(B1ADDR),
+ .q_b(B1DATA),
+ .clock0(CLK1),
+ .clock1(CLK1)
+);
+
+endmodule
diff --git a/techlibs/intel_alm/common/dff_sim.v b/techlibs/intel_alm/common/dff_sim.v
index d2cff0adb..8d58bf614 100644
--- a/techlibs/intel_alm/common/dff_sim.v
+++ b/techlibs/intel_alm/common/dff_sim.v
@@ -56,7 +56,9 @@
(* abc9_box, lib_whitebox *)
module MISTRAL_FF(
- input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA,
+ input DATAIN,
+ (* clkbuf_sink *) input CLK,
+ input ACLR, ENA, SCLR, SLOAD, SDATA,
output reg Q
);
@@ -75,6 +77,21 @@ specify
if (ACLR === 1'b0) (ACLR => Q) = 282;
endspecify
`endif
+`ifdef arriav
+specify
+ if (ENA && ACLR !== 1'b0 && !SCLR && !SLOAD) (posedge CLK => (Q : DATAIN)) = 470;
+ if (ENA && SCLR) (posedge CLK => (Q : 1'b0)) = 633;
+ if (ENA && !SCLR && SLOAD) (posedge CLK => (Q : SDATA)) = 439;
+
+ $setup(DATAIN, posedge CLK, /* -170 */ 0);
+ $setup(ENA, posedge CLK, /* -170 */ 0);
+ $setup(SCLR, posedge CLK, /* -170 */ 0);
+ $setup(SLOAD, posedge CLK, /* -170 */ 0);
+ $setup(SDATA, posedge CLK, /* -170 */ 0);
+
+ if (ACLR === 1'b0) (ACLR => Q) = 215;
+endspecify
+`endif
`ifdef cyclone10gx
specify
// TODO (long-term): investigate these numbers.
diff --git a/techlibs/intel_alm/common/dsp_sim.v b/techlibs/intel_alm/common/dsp_sim.v
index bdb6d18d5..3d4b5590b 100644
--- a/techlibs/intel_alm/common/dsp_sim.v
+++ b/techlibs/intel_alm/common/dsp_sim.v
@@ -1,14 +1,31 @@
+`default_nettype none
+
(* abc9_box *)
module MISTRAL_MUL27X27(input [26:0] A, input [26:0] B, output [53:0] Y);
parameter A_SIGNED = 1;
parameter B_SIGNED = 1;
+`ifdef cyclonev
+specify
+ (A *> Y) = 3732;
+ (B *> Y) = 3928;
+endspecify
+`endif
+`ifdef arriav
+// NOTE: Arria V appears to have only one set of timings for all DSP modes...
+specify
+ (A *> Y) = 1895;
+ (B *> Y) = 2053;
+endspecify
+`endif
+`ifdef cyclone10gx
// TODO: Cyclone 10 GX timings; the below are for Cyclone V
specify
(A *> Y) = 3732;
(B *> Y) = 3928;
endspecify
+`endif
wire [53:0] A_, B_;
@@ -32,11 +49,26 @@ module MISTRAL_MUL18X18(input [17:0] A, input [17:0] B, output [35:0] Y);
parameter A_SIGNED = 1;
parameter B_SIGNED = 1;
+`ifdef cyclonev
+specify
+ (A *> Y) = 3180;
+ (B *> Y) = 3982;
+endspecify
+`endif
+`ifdef arriav
+// NOTE: Arria V appears to have only one set of timings for all DSP modes...
+specify
+ (A *> Y) = 1895;
+ (B *> Y) = 2053;
+endspecify
+`endif
+`ifdef cyclone10gx
// TODO: Cyclone 10 GX timings; the below are for Cyclone V
specify
(A *> Y) = 3180;
(B *> Y) = 3982;
endspecify
+`endif
wire [35:0] A_, B_;
@@ -60,11 +92,26 @@ module MISTRAL_MUL9X9(input [8:0] A, input [8:0] B, output [17:0] Y);
parameter A_SIGNED = 1;
parameter B_SIGNED = 1;
+`ifdef cyclonev
+specify
+ (A *> Y) = 2818;
+ (B *> Y) = 3051;
+endspecify
+`endif
+`ifdef arriav
+// NOTE: Arria V appears to have only one set of timings for all DSP modes...
+specify
+ (A *> Y) = 1895;
+ (B *> Y) = 2053;
+endspecify
+`endif
+`ifdef cyclone10gx
// TODO: Cyclone 10 GX timings; the below are for Cyclone V
specify
(A *> Y) = 2818;
(B *> Y) = 3051;
endspecify
+`endif
wire [17:0] A_, B_;
diff --git a/techlibs/intel_alm/common/megafunction_bb.v b/techlibs/intel_alm/common/megafunction_bb.v
index 874f293b1..d4ed95173 100644
--- a/techlibs/intel_alm/common/megafunction_bb.v
+++ b/techlibs/intel_alm/common/megafunction_bb.v
@@ -627,3 +627,91 @@ output [port_b_data_width-1:0] portbdataout;
input clk0, portawe, portbre;
endmodule
+
+(* blackbox *)
+module cyclone10gx_io_ibuf(i, ibar, dynamicterminationcontrol, o);
+
+parameter differential_mode ="false";
+parameter bus_hold = "false";
+parameter simulate_z_as = "Z";
+parameter lpm_type = "cyclone10gx_io_ibuf";
+
+(* iopad_external_pin *) input i;
+(* iopad_external_pin *) input ibar;
+input dynamicterminationcontrol;
+output o;
+
+endmodule
+
+(* blackbox *)
+module cyclone10gx_io_obuf(i, oe, dynamicterminationcontrol, seriesterminationcontrol, parallelterminationcontrol, devoe, o, obar);
+
+parameter open_drain_output = "false";
+parameter bus_hold = "false";
+parameter shift_series_termination_control = "false";
+parameter sim_dynamic_termination_control_is_connected = "false";
+parameter lpm_type = "cyclone10gx_io_obuf";
+
+input i;
+input oe;
+input devoe;
+input dynamicterminationcontrol;
+input [15:0] seriesterminationcontrol;
+input [15:0] parallelterminationcontrol;
+(* iopad_external_pin *) output o;
+(* iopad_external_pin *) output obar;
+
+endmodule
+
+(* blackbox *)
+module cyclonev_clkena(inclk, ena, enaout, outclk);
+
+parameter clock_type = "auto";
+parameter ena_register_mode = "always enabled";
+parameter lpm_type = "cyclonev_clkena";
+parameter ena_register_power_up = "high";
+parameter disable_mode = "low";
+parameter test_syn = "high";
+
+input inclk;
+input ena;
+output enaout;
+output outclk;
+
+endmodule
+
+(* blackbox *)
+module cyclone10gx_clkena(inclk, ena, enaout, outclk);
+
+parameter clock_type = "auto";
+parameter ena_register_mode = "always enabled";
+parameter lpm_type = "cyclone10gx_clkena";
+parameter ena_register_power_up = "high";
+parameter disable_mode = "low";
+parameter test_syn = "high";
+
+input inclk;
+input ena;
+output enaout;
+output outclk;
+
+endmodule
+
+// Internal interfaces
+(* keep *)
+module cyclonev_oscillator(oscena, clkout, clkout1);
+
+input oscena;
+output clkout;
+output clkout1;
+
+endmodule
+
+// HPS interfaces
+(* keep *)
+module cyclonev_hps_interface_mpu_general_purpose(gp_in, gp_out);
+
+input [31:0] gp_in;
+output [31:0] gp_out;
+
+endmodule
diff --git a/techlibs/intel_alm/common/mem_sim.v b/techlibs/intel_alm/common/mem_sim.v
index e09aafaa2..370e17f27 100644
--- a/techlibs/intel_alm/common/mem_sim.v
+++ b/techlibs/intel_alm/common/mem_sim.v
@@ -50,10 +50,39 @@
// model can be treated as always returning a defined result.
(* abc9_box, lib_whitebox *)
-module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1ADDR, output B1DATA);
+module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN,
+ (* clkbuf_sink *) input CLK1,
+ input [4:0] B1ADDR, output B1DATA);
reg [31:0] mem = 32'b0;
+`ifdef cyclonev
+specify
+ $setup(A1ADDR, posedge CLK1, 86);
+ $setup(A1DATA, posedge CLK1, 86);
+ $setup(A1EN, posedge CLK1, 86);
+
+ (B1ADDR[0] => B1DATA) = 487;
+ (B1ADDR[1] => B1DATA) = 475;
+ (B1ADDR[2] => B1DATA) = 382;
+ (B1ADDR[3] => B1DATA) = 284;
+ (B1ADDR[4] => B1DATA) = 96;
+endspecify
+`endif
+`ifdef arriav
+specify
+ $setup(A1ADDR, posedge CLK1, 62);
+ $setup(A1DATA, posedge CLK1, 62);
+ $setup(A1EN, posedge CLK1, 62);
+
+ (B1ADDR[0] => B1DATA) = 370;
+ (B1ADDR[1] => B1DATA) = 292;
+ (B1ADDR[2] => B1DATA) = 218;
+ (B1ADDR[3] => B1DATA) = 74;
+ (B1ADDR[4] => B1DATA) = 177;
+endspecify
+`endif
+`ifdef cyclone10gx
// TODO: Cyclone 10 GX timings; the below timings are for Cyclone V
specify
$setup(A1ADDR, posedge CLK1, 86);
@@ -66,6 +95,7 @@ specify
(B1ADDR[3] => B1DATA) = 284;
(B1ADDR[4] => B1DATA) = 96;
endspecify
+`endif
always @(posedge CLK1)
if (A1EN) mem[A1ADDR] <= A1DATA;
@@ -83,7 +113,7 @@ module MISTRAL_M10K(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
parameter CFG_ABITS = 10;
parameter CFG_DBITS = 10;
-input CLK1;
+(* clkbuf_sink *) input CLK1;
input [CFG_ABITS-1:0] A1ADDR, B1ADDR;
input [CFG_DBITS-1:0] A1DATA;
input A1EN, B1EN;
@@ -91,12 +121,28 @@ output reg [CFG_DBITS-1:0] B1DATA;
reg [2**CFG_ABITS * CFG_DBITS - 1 : 0] mem = 0;
+`ifdef cyclonev
+specify
+ $setup(A1ADDR, posedge CLK1, 125);
+ $setup(A1DATA, posedge CLK1, 97);
+ $setup(A1EN, posedge CLK1, 140);
+ $setup(B1ADDR, posedge CLK1, 125);
+ $setup(B1EN, posedge CLK1, 161);
+
+ if (B1EN) (posedge CLK1 => (B1DATA : A1DATA)) = 1004;
+endspecify
+`endif
+`ifdef arriav
specify
- $setup(A1ADDR, posedge CLK1, 0);
- $setup(A1DATA, posedge CLK1, 0);
+ $setup(A1ADDR, posedge CLK1, 97);
+ $setup(A1DATA, posedge CLK1, 74);
+ $setup(A1EN, posedge CLK1, 109);
+ $setup(B1ADDR, posedge CLK1, 97);
+ $setup(B1EN, posedge CLK1, 126);
- if (B1EN) (posedge CLK1 => (B1DATA : A1DATA)) = 0;
+ if (B1EN) (posedge CLK1 => (B1DATA : A1DATA)) = 787;
endspecify
+`endif
always @(posedge CLK1) begin
if (A1EN)
diff --git a/techlibs/intel_alm/common/misc_sim.v b/techlibs/intel_alm/common/misc_sim.v
new file mode 100644
index 000000000..b1f970a21
--- /dev/null
+++ b/techlibs/intel_alm/common/misc_sim.v
@@ -0,0 +1,21 @@
+module MISTRAL_IB((* iopad_external_pin *) input PAD, output O);
+ assign O = PAD;
+endmodule
+
+module MISTRAL_OB((* iopad_external_pin *) output PAD, input I);
+ assign PAD = I;
+endmodule
+
+module MISTRAL_IO((* iopad_external_pin *) inout PAD, input I, input OE, output O);
+ assign PAD = OE ? I : 1'bz;
+ assign O = PAD;
+endmodule
+
+// Eventually, we should support clock enables and model them here too.
+// For now, CLKENA is used as a basic entry point to global routing.
+module MISTRAL_CLKBUF (
+ input A,
+ (* clkbuf_driver *) output Q
+);
+ assign Q = A;
+endmodule \ No newline at end of file
diff --git a/techlibs/intel_alm/common/quartus_rename.v b/techlibs/intel_alm/common/quartus_rename.v
index 3b4628675..5850f6907 100644
--- a/techlibs/intel_alm/common/quartus_rename.v
+++ b/techlibs/intel_alm/common/quartus_rename.v
@@ -2,11 +2,28 @@
`define LCELL cyclonev_lcell_comb
`define MAC cyclonev_mac
`define MLAB cyclonev_mlab_cell
+`define RAM_BLOCK cyclonev_ram_block
+`define IBUF cyclonev_io_ibuf
+`define OBUF cyclonev_io_obuf
+`define CLKENA cyclonev_clkena
+`endif
+`ifdef arriav
+`define LCELL arriav_lcell_comb
+`define MAC arriav_mac
+`define MLAB arriav_mlab_cell
+`define RAM_BLOCK arriav_ram_block
+`define IBUF arriav_io_ibuf
+`define OBUF arriav_io_obuf
+`define CLKENA arriav_clkena
`endif
`ifdef cyclone10gx
`define LCELL cyclone10gx_lcell_comb
`define MAC cyclone10gx_mac
`define MLAB cyclone10gx_mlab_cell
+`define RAM_BLOCK cyclone10gx_ram_block
+`define IBUF cyclone10gx_io_ibuf
+`define OBUF cyclone10gx_io_obuf
+`define CLKENA cyclone10gx_clkena
`endif
module __MISTRAL_VCC(output Q);
@@ -140,7 +157,7 @@ output [CFG_DBITS-1:0] B1DATA;
// Much like the MLAB, the M10K has mem_init[01234] parameters which would let
// you initialise the RAM cell via hex literals. If they were implemented.
-cyclonev_ram_block #(
+`RAM_BLOCK #(
.operation_mode("dual_port"),
.logical_ram_name(_TECHMAP_CELLNAME_),
.port_a_address_width(CFG_ABITS),
@@ -233,3 +250,57 @@ parameter B_SIGNED = 1;
);
endmodule
+
+module MISTRAL_IB(input PAD, output O);
+`IBUF #(
+ .bus_hold("false"),
+ .differential_mode("false")
+) _TECHMAP_REPLACE_ (
+ .i(PAD),
+ .o(O)
+);
+endmodule
+
+module MISTRAL_OB(output PAD, input I, OE);
+`OBUF #(
+ .bus_hold("false"),
+ .differential_mode("false")
+) _TECHMAP_REPLACE_ (
+ .i(I),
+ .o(PAD),
+ .oe(OE)
+);
+endmodule
+
+module MISTRAL_IO(output PAD, input I, OE, output O);
+`IBUF #(
+ .bus_hold("false"),
+ .differential_mode("false")
+) ibuf (
+ .i(PAD),
+ .o(O)
+);
+
+`OBUF #(
+ .bus_hold("false"),
+ .differential_mode("false")
+) obuf (
+ .i(I),
+ .o(PAD),
+ .oe(OE)
+);
+endmodule
+
+module MISTRAL_CLKBUF (input A, output Q);
+`CLKENA #(
+ .clock_type("auto"),
+ .ena_register_mode("always enabled"),
+ .ena_register_power_up("high"),
+ .disable_mode("low"),
+ .test_syn("high")
+) _TECHMAP_REPLACE_ (
+ .inclk(A),
+ .ena(1'b1),
+ .outclk(Q)
+);
+endmodule
diff --git a/techlibs/intel_alm/cyclonev/cells_sim.v b/techlibs/intel_alm/cyclonev/cells_sim.v
index 9b2a10e72..14bb756cf 100644
--- a/techlibs/intel_alm/cyclonev/cells_sim.v
+++ b/techlibs/intel_alm/cyclonev/cells_sim.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -26,16 +26,34 @@ endmodule // GND
/* Altera Cyclone V devices Input Buffer Primitive */
module cyclonev_io_ibuf
- (output o, input i, input ibar);
- assign ibar = ibar;
+ (output o,
+ (* iopad_external_pin *) input i,
+ (* iopad_external_pin *) input ibar,
+ input dynamicterminationcontrol);
+
+ parameter differential_mode = "false";
+ parameter bus_hold = "false";
+ parameter simulate_z_as = "Z";
+ parameter lpm_type = "cyclonev_io_ibuf";
+
assign o = i;
endmodule // cyclonev_io_ibuf
/* Altera Cyclone V devices Output Buffer Primitive */
module cyclonev_io_obuf
- (output o, input i, input oe);
- assign o = i;
- assign oe = oe;
+ ((* iopad_external_pin *) output o,
+ input i, oe, dynamicterminationcontrol,
+ input [15:0] seriesterminationcontrol, parallelterminationcontrol,
+ input devoe,
+ (* iopad_external_pin *) output obar);
+
+ parameter open_drain_output = "false";
+ parameter bus_hold = "false";
+ parameter shift_series_termination_control = "false";
+ parameter sim_dynamic_termination_control_is_connected = "false";
+ parameter lpm_type = "cyclonev_io_obuf";
+
+ assign o = oe ? i : 1'bz;
endmodule // cyclonev_io_obuf
/* Altera Cyclone V LUT Primitive */
diff --git a/techlibs/intel_alm/synth_intel_alm.cc b/techlibs/intel_alm/synth_intel_alm.cc
index 6719eb65c..34a5ffa5d 100644
--- a/techlibs/intel_alm/synth_intel_alm.cc
+++ b/techlibs/intel_alm/synth_intel_alm.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Claire Wolf <claire@symbioticeda.com>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* Copyright (C) 2019 Dan Ravensloft <dan.ravensloft@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -43,6 +43,7 @@ struct SynthIntelALMPass : public ScriptPass {
log(" -family <family>\n");
log(" target one of:\n");
log(" \"cyclonev\" - Cyclone V (default)\n");
+ log(" \"arriav\" - Arria V (non-GZ)");
log(" \"cyclone10gx\" - Cyclone 10GX\n");
log("\n");
log(" -vqm <file>\n");
@@ -72,13 +73,19 @@ struct SynthIntelALMPass : public ScriptPass {
log(" -nodsp\n");
log(" do not map multipliers to MISTRAL_MUL cells\n");
log("\n");
+ log(" -noiopad\n");
+ log(" do not instantiate IO buffers\n");
+ log("\n");
+ log(" -noclkbuf\n");
+ log(" do not insert global clock buffers\n");
+ log("\n");
log("The following commands are executed by this synthesis command:\n");
help_script();
log("\n");
}
string top_opt, family_opt, bram_type, vout_file;
- bool flatten, quartus, nolutram, nobram, dff, nodsp;
+ bool flatten, quartus, nolutram, nobram, dff, nodsp, noiopad, noclkbuf;
void clear_flags() override
{
@@ -92,6 +99,8 @@ struct SynthIntelALMPass : public ScriptPass {
nobram = false;
dff = false;
nodsp = false;
+ noiopad = false;
+ noclkbuf = false;
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -146,6 +155,14 @@ struct SynthIntelALMPass : public ScriptPass {
dff = true;
continue;
}
+ if (args[argidx] == "-noiopad") {
+ noiopad = true;
+ continue;
+ }
+ if (args[argidx] == "-noclkbuf") {
+ noclkbuf = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -153,10 +170,14 @@ struct SynthIntelALMPass : public ScriptPass {
if (!design->full_selection())
log_cmd_error("This command only operates on fully selected designs!\n");
- if (family_opt == "cyclonev") {
+ if (family_opt == "cyclonev" || family_opt == "arriav") {
bram_type = "m10k";
} else if (family_opt == "cyclone10gx") {
bram_type = "m20k";
+ } else if (family_opt == "arriva") {
+ // I have typoed "arriav" as "arriva" (a local bus company)
+ // so many times I thought it would be funny to have an easter egg.
+ log_cmd_error("synth_intel_alm cannot synthesize for bus companies. (did you mean '-family arriav'?)\n");
} else {
log_cmd_error("Invalid family specified: '%s'\n", family_opt.c_str());
}
@@ -183,8 +204,8 @@ struct SynthIntelALMPass : public ScriptPass {
run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dff_sim.v", family_opt.c_str()));
run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dsp_sim.v", family_opt.c_str()));
run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/mem_sim.v", family_opt.c_str()));
+ run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/misc_sim.v", family_opt.c_str()));
run(stringf("read_verilog -specify -lib -D %s -icells +/intel_alm/common/abc9_model.v", family_opt.c_str()));
-
// Misc and common cells
run("read_verilog -lib +/intel/common/altpll_bb.v");
run("read_verilog -lib +/intel_alm/common/megafunction_bb.v");
@@ -213,12 +234,12 @@ struct SynthIntelALMPass : public ScriptPass {
if (help_mode) {
run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)");
} else if (!nodsp) {
- // Cyclone V supports 9x9 multiplication, Cyclone 10 GX does not.
+ // Cyclone V/Arria V supports 9x9 multiplication, Cyclone 10 GX does not.
run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=27 -D DSP_B_MAXWIDTH=27 -D DSP_A_MINWIDTH=19 -D DSP_B_MINWIDTH=4 -D DSP_NAME=__MUL27X27");
run("chtype -set $mul t:$__soft_mul");
run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=27 -D DSP_B_MAXWIDTH=27 -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=19 -D DSP_NAME=__MUL27X27");
run("chtype -set $mul t:$__soft_mul");
- if (family_opt == "cyclonev") {
+ if (family_opt == "cyclonev" || family_opt == "arriav") {
run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=10 -D DSP_B_MINWIDTH=4 -D DSP_NAME=__MUL18X18");
run("chtype -set $mul t:$__soft_mul");
run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=10 -D DSP_NAME=__MUL18X18");
@@ -231,6 +252,8 @@ struct SynthIntelALMPass : public ScriptPass {
}
}
run("alumacc");
+ if (!noiopad)
+ run("iopadmap -bits -outpad MISTRAL_OB I:PAD -inpad MISTRAL_IB O:PAD -toutpad MISTRAL_IO OE:O:PAD -tinoutpad MISTRAL_IO OE:O:I:PAD A:top", "(unless -noiopad)");
run("techmap -map +/intel_alm/common/arith_alm_map.v -map +/intel_alm/common/dsp_map.v");
run("opt");
run("memory -nomap");
@@ -258,6 +281,8 @@ struct SynthIntelALMPass : public ScriptPass {
run("techmap -map +/intel_alm/common/dff_map.v");
run("opt -full -undriven -mux_undef");
run("clean -purge");
+ if (!noclkbuf)
+ run("clkbufmap -buf MISTRAL_CLKBUF Q:A", "(unless -noclkbuf)");
}
if (check_label("map_luts")) {
@@ -274,6 +299,7 @@ struct SynthIntelALMPass : public ScriptPass {
run("hierarchy -check");
run("stat");
run("check");
+ run("blackbox =A:whitebox");
}
if (check_label("quartus")) {
diff --git a/techlibs/machxo2/cells_map.v b/techlibs/machxo2/cells_map.v
index 82eb10d95..9c370f246 100644
--- a/techlibs/machxo2/cells_map.v
+++ b/techlibs/machxo2/cells_map.v
@@ -30,5 +30,5 @@ module \$_DFF_P_ (input D, C, output Q); FACADE_FF #(.CEMUX("1"), .CLKMUX("CLK"
// IO- "$__" cells for the iopadmap pass.
module \$__FACADE_OUTPAD (input I, output O); FACADE_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.PAD(O), .I(I), .T(1'b0)); endmodule
module \$__FACADE_INPAD (input I, output O); FACADE_IO #(.DIR("INPUT")) _TECHMAP_REPLACE_ (.PAD(I), .O(O)); endmodule
-module \$__FACADE_TOUTPAD (input I, OE, output O); FACADE_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.PAD(O), .I(I), .T(~OE)); endmodule
-module \$__FACADE_TINOUTPAD (input I, OE, output O, inout B); FACADE_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.PAD(B), .I(I), .O(O), .T(~OE)); endmodule
+module \$__FACADE_TOUTPAD (input I, T, output O); FACADE_IO #(.DIR("OUTPUT")) _TECHMAP_REPLACE_ (.PAD(O), .I(I), .T(T)); endmodule
+module \$__FACADE_TINOUTPAD (input I, T, output O, inout B); FACADE_IO #(.DIR("BIDIR")) _TECHMAP_REPLACE_ (.PAD(B), .I(I), .O(O), .T(T)); endmodule
diff --git a/techlibs/machxo2/cells_sim.v b/techlibs/machxo2/cells_sim.v
index 161ddfe2e..dc68a3127 100644
--- a/techlibs/machxo2/cells_sim.v
+++ b/techlibs/machxo2/cells_sim.v
@@ -207,6 +207,6 @@ module \$__FACADE_OUTPAD (input I, output O); endmodule
(* blackbox *)
module \$__FACADE_INPAD (input I, output O); endmodule
(* blackbox *)
-module \$__FACADE_TOUTPAD (input I, OE, output O); endmodule
+module \$__FACADE_TOUTPAD (input I, T, output O); endmodule
(* blackbox *)
-module \$__FACADE_TINOUTPAD (input I, OE, output O, inout B); endmodule
+module \$__FACADE_TINOUTPAD (input I, T, output O, inout B); endmodule
diff --git a/techlibs/machxo2/synth_machxo2.cc b/techlibs/machxo2/synth_machxo2.cc
index bd56fbba9..e86ec5aaf 100644
--- a/techlibs/machxo2/synth_machxo2.cc
+++ b/techlibs/machxo2/synth_machxo2.cc
@@ -185,7 +185,7 @@ struct SynthMachXO2Pass : public ScriptPass
{
if (!noiopad || help_mode)
{
- run("iopadmap -bits -outpad $__FACADE_OUTPAD I:O -inpad $__FACADE_INPAD O:I -toutpad $__FACADE_TOUTPAD OE:I:O -tinoutpad $__FACADE_TINOUTPAD OE:O:I:B A:top");
+ run("iopadmap -bits -outpad $__FACADE_OUTPAD I:O -inpad $__FACADE_INPAD O:I -toutpad $__FACADE_TOUTPAD ~T:I:O -tinoutpad $__FACADE_TINOUTPAD ~T:O:I:B A:top");
run("attrmvcp -attr src -attr LOC t:$__FACADE_OUTPAD %x:+[O] t:$__FACADE_TOUTPAD %x:+[O] t:$__FACADE_TINOUTPAD %x:+[B]");
run("attrmvcp -attr src -attr LOC -driven t:$__FACADE_INPAD %x:+[I]");
}
@@ -212,6 +212,7 @@ struct SynthMachXO2Pass : public ScriptPass
{
run("hierarchy -check");
run("stat");
+ run("blackbox =A:whitebox");
}
if (check_label("blif"))
diff --git a/techlibs/nexus/arith_map.v b/techlibs/nexus/arith_map.v
index ce14a15ea..81ab7ba54 100644
--- a/techlibs/nexus/arith_map.v
+++ b/techlibs/nexus/arith_map.v
@@ -1,8 +1,8 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Claire Xen <claire@symbioticeda.com>
- * Copyright (C) 2018 David Shah <dave@ds0.me>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
+ * Copyright (C) 2018 gatecat <gatecat@ds0.me>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -90,7 +90,7 @@ module _80_nexus_alu (A, B, CI, BI, X, Y, CO);
assign CO[i] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i]));
if (i+1 < Y_WIDTH) begin
- assign CO[i + 1] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i]));
+ assign CO[i + 1] = (AA[i + 1] && BB[i + 1]) || ((Y[i + 1] ^ AA[i + 1] ^ BB[i + 1]) && (AA[i + 1] || BB[i + 1]));
assign Y[i+1] = Y1[i];
end
end endgenerate
diff --git a/techlibs/nexus/cells_map.v b/techlibs/nexus/cells_map.v
index 86911d7a0..b70edbcf4 100644
--- a/techlibs/nexus/cells_map.v
+++ b/techlibs/nexus/cells_map.v
@@ -53,14 +53,6 @@ module \$_DFFE_PP1P_ (input D, C, E, R, output Q); \$__FF_ASYNCLSR #(1) _TECHM
module \$_SDFFE_PP0P_ (input D, C, E, R, output Q); \$__FF_SYNCLSR #(0) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(E), .Q(Q)); endmodule
module \$_SDFFE_PP1P_ (input D, C, E, R, output Q); \$__FF_SYNCLSR #(1) _TECHMAP_REPLACE_ (.D(D), .C(C), .R(R), .E(E), .Q(Q)); endmodule
-module \$__NX_TINOUTPAD (input I, OE, output O, inout B);
- BB _TECHMAP_REPLACE_ (.I(I), .O(O), .T(~OE), .B(B));
-endmodule
-
-module \$__NX_TOUTPAD (input I, OE, output O);
- OBZ _TECHMAP_REPLACE_ (.I(I), .O(), .T(~OE), .O(O));
-endmodule
-
`ifndef NO_LUT
module \$lut (A, Y);
parameter WIDTH = 0;
diff --git a/techlibs/nexus/cells_sim.v b/techlibs/nexus/cells_sim.v
index 1e876a210..d1c8bf0d7 100644
--- a/techlibs/nexus/cells_sim.v
+++ b/techlibs/nexus/cells_sim.v
@@ -54,8 +54,8 @@ endmodule
// Bidirectional IO buffer
module BB(input T, I, output O,
(* iopad_external_pin *) inout B);
- assign B = T ? 1'bz : O;
- assign I = B;
+ assign B = T ? 1'bz : I;
+ assign O = B;
endmodule
// Input buffer
diff --git a/techlibs/nexus/synth_nexus.cc b/techlibs/nexus/synth_nexus.cc
index 7f36eb282..03bff0649 100644
--- a/techlibs/nexus/synth_nexus.cc
+++ b/techlibs/nexus/synth_nexus.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2020 David Shah <dave@ds0.me>
+ * Copyright (C) 2020 gatecat <gatecat@ds0.me>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -333,7 +333,7 @@ struct SynthNexusPass : public ScriptPass
else
run("techmap -map +/techmap.v -map +/nexus/arith_map.v");
if (help_mode || !noiopad)
- run("iopadmap -bits -outpad OB I:O -inpad IB O:I -toutpad $__NX_TOUTPAD OE:I:O -tinoutpad $__NX_TINOUTPAD OE:O:I:B A:top", "(skip if '-noiopad')");
+ run("iopadmap -bits -outpad OB I:O -inpad IB O:I -toutpad OBZ ~T:I:O -tinoutpad BB ~T:O:I:B A:top", "(skip if '-noiopad')");
run("opt -fast");
if (retime || help_mode)
run("abc -dff -D 1", "(only if -retime)");
@@ -406,6 +406,7 @@ struct SynthNexusPass : public ScriptPass
run("hierarchy -check");
run("stat");
run("check -noinit");
+ run("blackbox =A:whitebox");
}
if (check_label("json"))
diff --git a/techlibs/quicklogic/Makefile.inc b/techlibs/quicklogic/Makefile.inc
new file mode 100644
index 000000000..51eb28d44
--- /dev/null
+++ b/techlibs/quicklogic/Makefile.inc
@@ -0,0 +1,13 @@
+OBJS += techlibs/quicklogic/synth_quicklogic.o
+
+$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/pp3_ffs_map.v))
+$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/pp3_lut_map.v))
+$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/pp3_latches_map.v))
+$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/pp3_cells_map.v))
+$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/cells_sim.v))
+$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/lut_sim.v))
+$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/pp3_cells_sim.v))
+
+$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/abc9_model.v))
+$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/abc9_map.v))
+$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/abc9_unmap.v))
diff --git a/techlibs/quicklogic/abc9_map.v b/techlibs/quicklogic/abc9_map.v
new file mode 100644
index 000000000..46c11d675
--- /dev/null
+++ b/techlibs/quicklogic/abc9_map.v
@@ -0,0 +1,26 @@
+// This file exists to map purely-synchronous flops to ABC9 flops, while
+// mapping flops with asynchronous-set/clear as boxes, this is because ABC9
+// doesn't support asynchronous-set/clear flops in sequential synthesis.
+
+module dffepc (
+ output Q,
+ input D,
+ input CLK,
+ input EN,
+ input CLR,
+ input PRE
+);
+
+parameter INIT = 1'b0;
+
+parameter _TECHMAP_CONSTMSK_CLR_ = 1'b0;
+parameter _TECHMAP_CONSTMSK_PRE_ = 1'b0;
+parameter _TECHMAP_CONSTVAL_CLR_ = 1'b0;
+parameter _TECHMAP_CONSTVAL_PRE_ = 1'b0;
+
+if (_TECHMAP_CONSTMSK_CLR_ != 1'b0 && _TECHMAP_CONSTMSK_PRE_ != 1'b0 && _TECHMAP_CONSTVAL_CLR_ == 1'b0 && _TECHMAP_CONSTVAL_PRE_ == 1'b0)
+ $__PP3_DFFEPC_SYNCONLY _TECHMAP_REPLACE_ (.Q(Q), .D(D), .CLK(CLK), .EN(EN));
+else
+ wire _TECHMAP_FAIL_ = 1;
+
+endmodule
diff --git a/techlibs/quicklogic/abc9_model.v b/techlibs/quicklogic/abc9_model.v
new file mode 100644
index 000000000..06d4a2a56
--- /dev/null
+++ b/techlibs/quicklogic/abc9_model.v
@@ -0,0 +1,11 @@
+(* abc9_flop, lib_whitebox *)
+module $__PP3_DFFEPC_SYNCONLY (
+ output Q,
+ input D,
+ input CLK,
+ input EN,
+);
+
+ dffepc ff (.Q(Q), .D(D), .CLK(CLK), .EN(EN), .PRE(1'b0), .CLR(1'b0));
+
+endmodule
diff --git a/techlibs/quicklogic/abc9_unmap.v b/techlibs/quicklogic/abc9_unmap.v
new file mode 100644
index 000000000..1681e01bb
--- /dev/null
+++ b/techlibs/quicklogic/abc9_unmap.v
@@ -0,0 +1,14 @@
+module $__PP3_DFFEPC_SYNCONLY (
+ output Q,
+ input D,
+ input CLK,
+ input EN,
+);
+
+// For some reason ABC9 adds init attributes to wires even though they were removed before mapping.
+// As a workaround, remove any init attributes that get reintroduced.
+wire _TECHMAP_REMOVEINIT_Q_ = 1;
+
+dffepc _TECHMAP_REPLACE_ (.Q(Q), .D(D), .CLK(CLK), .EN(EN), .PRE(1'b0), .CLR(1'b0));
+
+endmodule
diff --git a/techlibs/quicklogic/cells_sim.v b/techlibs/quicklogic/cells_sim.v
new file mode 100644
index 000000000..f24782ec3
--- /dev/null
+++ b/techlibs/quicklogic/cells_sim.v
@@ -0,0 +1,36 @@
+module inv (
+ output Q,
+ input A
+);
+ assign Q = A ? 0 : 1;
+endmodule
+
+module buff (
+ output Q,
+ input A
+);
+ assign Q = A;
+endmodule
+
+module logic_0 (
+ output A
+);
+ assign A = 0;
+endmodule
+
+module logic_1 (
+ output A
+);
+ assign A = 1;
+endmodule
+
+module gclkbuff (
+ input A,
+ output Z
+);
+ specify
+ (A => Z) = 0;
+ endspecify
+
+ assign Z = A;
+endmodule
diff --git a/techlibs/quicklogic/lut_sim.v b/techlibs/quicklogic/lut_sim.v
new file mode 100644
index 000000000..851ce4d68
--- /dev/null
+++ b/techlibs/quicklogic/lut_sim.v
@@ -0,0 +1,76 @@
+(* abc9_lut=1, lib_whitebox *)
+module LUT1 (
+ output O,
+ input I0
+);
+ parameter [1:0] INIT = 0;
+ parameter EQN = "(I0)";
+
+ // These timings are for PolarPro 3E; other families will need updating.
+ specify
+ (I0 => O) = 698; // FS -> FZ
+ endspecify
+
+ assign O = I0 ? INIT[1] : INIT[0];
+endmodule
+
+// TZ TSL TAB
+(* abc9_lut=2, lib_whitebox *)
+module LUT2 (
+ output O,
+ input I0, I1
+);
+ parameter [3:0] INIT = 4'h0;
+ parameter EQN = "(I0)";
+
+ // These timings are for PolarPro 3E; other families will need updating.
+ specify
+ (I0 => O) = 1251; // TAB -> TZ
+ (I1 => O) = 1406; // TSL -> TZ
+ endspecify
+
+ wire [1:0] s1 = I1 ? INIT[3:2] : INIT[1:0];
+ assign O = I0 ? s1[1] : s1[0];
+endmodule
+
+(* abc9_lut=2, lib_whitebox *)
+module LUT3 (
+ output O,
+ input I0, I1, I2
+);
+ parameter [7:0] INIT = 8'h0;
+ parameter EQN = "(I0)";
+
+ // These timings are for PolarPro 3E; other families will need updating.
+ specify
+ (I0 => O) = 1251; // TAB -> TZ
+ (I1 => O) = 1406; // TSL -> TZ
+ (I2 => O) = 1699; // ('TA1', 'TA2', 'TB1', 'TB2') -> TZ
+ endspecify
+
+ wire [3:0] s2 = I2 ? INIT[7:4] : INIT[3:0];
+ wire [1:0] s1 = I1 ? s2[3:2] : s2[1:0];
+ assign O = I0 ? s1[1] : s1[0];
+endmodule
+
+(* abc9_lut=4, lib_whitebox *)
+module LUT4 (
+ output O,
+ input I0, I1, I2, I3
+);
+ parameter [15:0] INIT = 16'h0;
+ parameter EQN = "(I0)";
+
+ // These timings are for PolarPro 3E; other families will need updating.
+ specify
+ (I0 => O) = 995; // TBS -> CZ
+ (I1 => O) = 1437; // ('TAB', 'BAB') -> CZ
+ (I2 => O) = 1593; // ('TSL', 'BSL') -> CZ
+ (I3 => O) = 1887; // ('TA1', 'TA2', 'TB1', 'TB2', 'BA1', 'BA2', 'BB1', 'BB2') -> CZ
+ endspecify
+
+ wire [7:0] s3 = I3 ? INIT[15:8] : INIT[7:0];
+ wire [3:0] s2 = I2 ? s3[7:4] : s3[3:0];
+ wire [1:0] s1 = I1 ? s2[3:2] : s2[1:0];
+ assign O = I0 ? s1[1] : s1[0];
+endmodule
diff --git a/techlibs/quicklogic/pp3_cells_map.v b/techlibs/quicklogic/pp3_cells_map.v
new file mode 100644
index 000000000..10e270d4e
--- /dev/null
+++ b/techlibs/quicklogic/pp3_cells_map.v
@@ -0,0 +1,36 @@
+module \$_MUX8_ (
+ A, B, C, D, E, F, G, H, S, T, U, Y
+);
+ input A, B, C, D, E, F, G, H, S, T, U;
+ output Y;
+ mux8x0 _TECHMAP_REPLACE_ (
+ .A(A),
+ .B(B),
+ .C(C),
+ .D(D),
+ .E(E),
+ .F(F),
+ .G(G),
+ .H(H),
+ .S0(S),
+ .S1(T),
+ .S2(U),
+ .Q(Y)
+ );
+endmodule
+
+module \$_MUX4_ (
+ A, B, C, D, S, T, U, Y
+);
+ input A, B, C, D, S, T, U;
+ output Y;
+ mux4x0 _TECHMAP_REPLACE_ (
+ .A(A),
+ .B(B),
+ .C(C),
+ .D(D),
+ .S0(S),
+ .S1(T),
+ .Q(Y)
+ );
+endmodule
diff --git a/techlibs/quicklogic/pp3_cells_sim.v b/techlibs/quicklogic/pp3_cells_sim.v
new file mode 100644
index 000000000..5820d7a9e
--- /dev/null
+++ b/techlibs/quicklogic/pp3_cells_sim.v
@@ -0,0 +1,329 @@
+module inpad (
+ output Q,
+ (* iopad_external_pin *)
+ input P
+);
+ specify
+ (P => Q) = 0;
+ endspecify
+ assign Q = P;
+endmodule
+
+module outpad (
+ (* iopad_external_pin *)
+ output P,
+ input A
+);
+ specify
+ (A => P) = 0;
+ endspecify
+ assign P = A;
+endmodule
+
+module ckpad (
+ output Q,
+ (* iopad_external_pin *)
+ input P
+);
+ specify
+ (P => Q) = 0;
+ endspecify
+ assign Q = P;
+endmodule
+
+module bipad (
+ input A,
+ input EN,
+ output Q,
+ (* iopad_external_pin *)
+ inout P
+);
+ assign Q = P;
+ assign P = EN ? A : 1'bz;
+endmodule
+
+module dff (
+ output reg Q,
+ input D,
+ (* clkbuf_sink *)
+ input CLK
+);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK) Q <= D;
+endmodule
+
+module dffc (
+ output reg Q,
+ input D,
+ (* clkbuf_sink *)
+ input CLK,
+ (* clkbuf_sink *)
+ input CLR
+);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+
+ always @(posedge CLK or posedge CLR)
+ if (CLR) Q <= 1'b0;
+ else Q <= D;
+endmodule
+
+module dffp (
+ output reg Q,
+ input D,
+ (* clkbuf_sink *)
+ input CLK,
+ (* clkbuf_sink *)
+ input PRE
+);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+
+ always @(posedge CLK or posedge PRE)
+ if (PRE) Q <= 1'b1;
+ else Q <= D;
+endmodule
+
+module dffpc (
+ output reg Q,
+ input D,
+ (* clkbuf_sink *)
+ input CLK,
+ (* clkbuf_sink *)
+ input CLR,
+ (* clkbuf_sink *)
+ input PRE
+);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+
+ always @(posedge CLK or posedge CLR or posedge PRE)
+ if (CLR) Q <= 1'b0;
+ else if (PRE) Q <= 1'b1;
+ else Q <= D;
+endmodule
+
+module dffe (
+ output reg Q,
+ input D,
+ (* clkbuf_sink *)
+ input CLK,
+ input EN
+);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+ always @(posedge CLK) if (EN) Q <= D;
+endmodule
+
+module dffec (
+ output reg Q,
+ input D,
+ (* clkbuf_sink *)
+ input CLK,
+ input EN,
+ (* clkbuf_sink *)
+ input CLR
+);
+ parameter [0:0] INIT = 1'b0;
+ initial Q = INIT;
+
+ always @(posedge CLK or posedge CLR)
+ if (CLR) Q <= 1'b0;
+ else if (EN) Q <= D;
+endmodule
+
+(* lib_whitebox *)
+module dffepc (
+ output reg Q,
+ input D,
+ (* clkbuf_sink *)
+ input CLK,
+ input EN,
+ (* clkbuf_sink *)
+ input CLR,
+ (* clkbuf_sink *)
+ input PRE
+);
+ parameter [0:0] INIT = 1'b0;
+
+ specify
+ if (EN) (posedge CLK => (Q : D)) = 1701; // QCK -> QZ
+ if (CLR) (CLR => Q) = 967; // QRT -> QZ
+ if (PRE) (PRE => Q) = 1252; // QST -> QZ
+ $setup(D, posedge CLK, 216); // QCK -> QDS
+ $setup(EN, posedge CLK, 590); // QCK -> QEN
+ endspecify
+
+ initial Q = INIT;
+ always @(posedge CLK or posedge CLR or posedge PRE)
+ if (CLR) Q <= 1'b0;
+ else if (PRE) Q <= 1'b1;
+ else if (EN) Q <= D;
+endmodule
+
+// FZ FS F2 (F1 TO 0)
+(* abc9_box, lib_whitebox *)
+module AND2I0 (
+ output Q,
+ input A, B
+);
+ specify
+ (A => Q) = 698; // FS -> FZ
+ (B => Q) = 639; // F2 -> FZ
+ endspecify
+
+ assign Q = A ? B : 0;
+endmodule
+
+(* abc9_box, lib_whitebox *)
+module mux2x0 (
+ output Q,
+ input S, A, B
+);
+ specify
+ (S => Q) = 698; // FS -> FZ
+ (A => Q) = 639; // F1 -> FZ
+ (B => Q) = 639; // F2 -> FZ
+ endspecify
+
+ assign Q = S ? B : A;
+endmodule
+
+(* abc9_box, lib_whitebox *)
+module mux2x1 (
+ output Q,
+ input S, A, B
+);
+ specify
+ (S => Q) = 698; // FS -> FZ
+ (A => Q) = 639; // F1 -> FZ
+ (B => Q) = 639; // F2 -> FZ
+ endspecify
+
+ assign Q = S ? B : A;
+endmodule
+
+(* abc9_box, lib_whitebox *)
+module mux4x0 (
+ output Q,
+ input S0, S1, A, B, C, D
+);
+ specify
+ (S0 => Q) = 1251; // TAB -> TZ
+ (S1 => Q) = 1406; // TSL -> TZ
+ (A => Q) = 1699; // TA1 -> TZ
+ (B => Q) = 1687; // TA2 -> TZ
+ (C => Q) = 1669; // TB1 -> TZ
+ (D => Q) = 1679; // TB2 -> TZ
+ endspecify
+
+ assign Q = S1 ? (S0 ? D : C) : (S0 ? B : A);
+endmodule
+
+// S0 BSL TSL
+// S1 BAB TAB
+// S2 TBS
+// A TA1
+// B TA2
+// C TB1
+// D TB2
+// E BA1
+// F BA2
+// G BB1
+// H BB2
+// Q CZ
+(* abc9_box, lib_whitebox *)
+module mux8x0 (
+ output Q,
+ input S0, S1, S2, A, B, C, D, E, F, G, H
+);
+ specify
+ (S0 => Q) = 1593; // ('TSL', 'BSL') -> CZ
+ (S1 => Q) = 1437; // ('TAB', 'BAB') -> CZ
+ (S2 => Q) = 995; // TBS -> CZ
+ (A => Q) = 1887; // TA1 -> CZ
+ (B => Q) = 1873; // TA2 -> CZ
+ (C => Q) = 1856; // TB1 -> CZ
+ (D => Q) = 1860; // TB2 -> CZ
+ (E => Q) = 1714; // BA1 -> CZ
+ (F => Q) = 1773; // BA2 -> CZ
+ (G => Q) = 1749; // BB1 -> CZ
+ (H => Q) = 1723; // BB2 -> CZ
+ endspecify
+
+ assign Q = S2 ? (S1 ? (S0 ? H : G) : (S0 ? F : E)) : (S1 ? (S0 ? D : C) : (S0 ? B : A));
+endmodule
+
+(* blackbox *)
+(* keep *)
+module qlal4s3b_cell_macro (
+ input WB_CLK,
+ input WBs_ACK,
+ input [31:0] WBs_RD_DAT,
+ output [3:0] WBs_BYTE_STB,
+ output WBs_CYC,
+ output WBs_WE,
+ output WBs_RD,
+ output WBs_STB,
+ output [16:0] WBs_ADR,
+ input [3:0] SDMA_Req,
+ input [3:0] SDMA_Sreq,
+ output [3:0] SDMA_Done,
+ output [3:0] SDMA_Active,
+ input [3:0] FB_msg_out,
+ input [7:0] FB_Int_Clr,
+ output FB_Start,
+ input FB_Busy,
+ output WB_RST,
+ output Sys_PKfb_Rst,
+ output Clk16,
+ output Clk16_Rst,
+ output Clk21,
+ output Clk21_Rst,
+ output Sys_Pclk,
+ output Sys_Pclk_Rst,
+ input Sys_PKfb_Clk,
+ input [31:0] FB_PKfbData,
+ output [31:0] WBs_WR_DAT,
+ input [3:0] FB_PKfbPush,
+ input FB_PKfbSOF,
+ input FB_PKfbEOF,
+ output [7:0] Sensor_Int,
+ output FB_PKfbOverflow,
+ output [23:0] TimeStamp,
+ input Sys_PSel,
+ input [15:0] SPIm_Paddr,
+ input SPIm_PEnable,
+ input SPIm_PWrite,
+ input [31:0] SPIm_PWdata,
+ output SPIm_PReady,
+ output SPIm_PSlvErr,
+ output [31:0] SPIm_Prdata,
+ input [15:0] Device_ID,
+ input [13:0] FBIO_In_En,
+ input [13:0] FBIO_Out,
+ input [13:0] FBIO_Out_En,
+ output [13:0] FBIO_In,
+ inout [13:0] SFBIO,
+ input Device_ID_6S,
+ input Device_ID_4S,
+ input SPIm_PWdata_26S,
+ input SPIm_PWdata_24S,
+ input SPIm_PWdata_14S,
+ input SPIm_PWdata_11S,
+ input SPIm_PWdata_0S,
+ input SPIm_Paddr_8S,
+ input SPIm_Paddr_6S,
+ input FB_PKfbPush_1S,
+ input FB_PKfbData_31S,
+ input FB_PKfbData_21S,
+ input FB_PKfbData_19S,
+ input FB_PKfbData_9S,
+ input FB_PKfbData_6S,
+ input Sys_PKfb_ClkS,
+ input FB_BusyS,
+ input WB_CLKS
+);
+
+endmodule
diff --git a/techlibs/quicklogic/pp3_ffs_map.v b/techlibs/quicklogic/pp3_ffs_map.v
new file mode 100644
index 000000000..73ba6c9c8
--- /dev/null
+++ b/techlibs/quicklogic/pp3_ffs_map.v
@@ -0,0 +1,4 @@
+module \$_DFFSRE_PPPP_ (input C, S, R, E, D, output Q);
+ wire _TECHMAP_REMOVEINIT_Q_ = 1;
+ dffepc #(.INIT(1'b0)) _TECHMAP_REPLACE_ (.CLK(C), .PRE(S), .CLR(R), .EN(E), .D(D), .Q(Q));
+endmodule
diff --git a/techlibs/quicklogic/pp3_latches_map.v b/techlibs/quicklogic/pp3_latches_map.v
new file mode 100644
index 000000000..240a3fb4e
--- /dev/null
+++ b/techlibs/quicklogic/pp3_latches_map.v
@@ -0,0 +1,11 @@
+module \$_DLATCH_P_ (E, D, Q);
+ wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
+ input E, D;
+ output Q = E ? D : Q;
+endmodule
+
+module \$_DLATCH_N_ (E, D, Q);
+ wire [1023:0] _TECHMAP_DO_ = "simplemap; opt";
+ input E, D;
+ output Q = !E ? D : Q;
+endmodule
diff --git a/techlibs/quicklogic/pp3_lut_map.v b/techlibs/quicklogic/pp3_lut_map.v
new file mode 100644
index 000000000..4c375c9fd
--- /dev/null
+++ b/techlibs/quicklogic/pp3_lut_map.v
@@ -0,0 +1,53 @@
+module \$lut (
+ A, Y
+);
+ parameter WIDTH = 0;
+ parameter LUT = 0;
+
+ input [WIDTH-1:0] A;
+ output Y;
+
+ generate
+ if (WIDTH == 1) begin
+ LUT1 #(
+ .EQN(""),
+ .INIT(LUT)
+ ) _TECHMAP_REPLACE_ (
+ .O(Y),
+ .I0(A[0])
+ );
+ end else if (WIDTH == 2) begin
+ LUT2 #(
+ .EQN(""),
+ .INIT(LUT)
+ ) _TECHMAP_REPLACE_ (
+ .O(Y),
+ .I0(A[0]),
+ .I1(A[1])
+ );
+ end else if (WIDTH == 3) begin
+ LUT3 #(
+ .EQN(""),
+ .INIT(LUT)
+ ) _TECHMAP_REPLACE_ (
+ .O(Y),
+ .I0(A[0]),
+ .I1(A[1]),
+ .I2(A[2])
+ );
+ end else if (WIDTH == 4) begin
+ LUT4 #(
+ .EQN(""),
+ .INIT(LUT)
+ ) _TECHMAP_REPLACE_ (
+ .O(Y),
+ .I0(A[0]),
+ .I1(A[1]),
+ .I2(A[2]),
+ .I3(A[3])
+ );
+ end else begin
+ wire _TECHMAP_FAIL_ = 1;
+ end
+ endgenerate
+endmodule
diff --git a/techlibs/quicklogic/synth_quicklogic.cc b/techlibs/quicklogic/synth_quicklogic.cc
new file mode 100644
index 000000000..754de2de6
--- /dev/null
+++ b/techlibs/quicklogic/synth_quicklogic.cc
@@ -0,0 +1,236 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 QuickLogic Corp.
+ *
+ * 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/celltypes.h"
+#include "kernel/log.h"
+#include "kernel/register.h"
+#include "kernel/rtlil.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct SynthQuickLogicPass : public ScriptPass {
+
+ SynthQuickLogicPass() : ScriptPass("synth_quicklogic", "Synthesis for QuickLogic FPGAs") {}
+
+ void help() override
+ {
+ log("\n");
+ log(" synth_quicklogic [options]\n");
+ log("This command runs synthesis for QuickLogic FPGAs\n");
+ log("\n");
+ log(" -top <module>\n");
+ log(" use the specified module as top module\n");
+ log("\n");
+ log(" -family <family>\n");
+ log(" run synthesis for the specified QuickLogic architecture\n");
+ log(" generate the synthesis netlist for the specified family.\n");
+ log(" supported values:\n");
+ log(" - pp3: PolarPro 3 \n");
+ log("\n");
+ log(" -blif <file>\n");
+ log(" write the design to the specified BLIF file. writing of an output file\n");
+ log(" is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -verilog <file>\n");
+ log(" write the design to the specified verilog file. writing of an output file\n");
+ log(" is omitted if this parameter is not specified.\n");
+ log("\n");
+ log(" -abc\n");
+ log(" use old ABC flow, which has generally worse mapping results but is less\n");
+ log(" likely to have bugs.\n");
+ log("\n");
+ log("The following commands are executed by this synthesis command:\n");
+ help_script();
+ log("\n");
+ }
+
+ string top_opt, blif_file, family, currmodule, verilog_file;
+ bool abc9;
+
+ void clear_flags() override
+ {
+ top_opt = "-auto-top";
+ blif_file = "";
+ verilog_file = "";
+ currmodule = "";
+ family = "pp3";
+ abc9 = true;
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ string run_from, run_to;
+ clear_flags();
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ if (args[argidx] == "-top" && argidx+1 < args.size()) {
+ top_opt = "-top " + args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-family" && argidx+1 < args.size()) {
+ family = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-blif" && argidx+1 < args.size()) {
+ blif_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-verilog" && argidx+1 < args.size()) {
+ verilog_file = args[++argidx];
+ continue;
+ }
+ if (args[argidx] == "-abc") {
+ abc9 = false;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (!design->full_selection())
+ log_cmd_error("This command only operates on fully selected designs!\n");
+
+ if (family != "pp3")
+ log_cmd_error("Invalid family specified: '%s'\n", family.c_str());
+
+ if (abc9 && design->scratchpad_get_int("abc9.D", 0) == 0) {
+ log_warning("delay target has not been set via SDC or scratchpad; assuming 12 MHz clock.\n");
+ design->scratchpad_set_int("abc9.D", 41667); // 12MHz = 83.33.. ns; divided by two to allow for interconnect delay.
+ }
+
+ log_header(design, "Executing SYNTH_QUICKLOGIC pass.\n");
+ log_push();
+
+ run_script(design, run_from, run_to);
+
+ log_pop();
+ }
+
+ void script() override
+ {
+ if (check_label("begin")) {
+ run(stringf("read_verilog -lib -specify +/quicklogic/cells_sim.v +/quicklogic/%s_cells_sim.v", family.c_str()));
+ run("read_verilog -lib -specify +/quicklogic/lut_sim.v");
+ run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
+ }
+
+ if (check_label("coarse")) {
+ run("proc");
+ run("flatten");
+ run("tribuf -logic");
+ run("deminout");
+ run("opt_expr");
+ run("opt_clean");
+ run("check");
+ run("opt -nodffe -nosdff");
+ run("fsm");
+ run("opt");
+ run("wreduce");
+ run("peepopt");
+ run("opt_clean");
+ run("share");
+ run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4");
+ run("opt_expr");
+ run("opt_clean");
+ run("alumacc");
+ run("pmuxtree");
+ run("opt");
+ run("memory -nomap");
+ run("opt_clean");
+ }
+
+ if (check_label("map_ffram")) {
+ run("opt -fast -mux_undef -undriven -fine");
+ run("memory_map -iattr -attr !ram_block -attr !rom_block -attr logic_block "
+ "-attr syn_ramstyle=auto -attr syn_ramstyle=registers "
+ "-attr syn_romstyle=auto -attr syn_romstyle=logic");
+ run("opt -undriven -fine");
+ }
+
+ if (check_label("map_gates")) {
+ run("techmap");
+ run("opt -fast");
+ run("muxcover -mux8 -mux4");
+ }
+
+ if (check_label("map_ffs")) {
+ run("opt_expr");
+ run("dfflegalize -cell $_DFFSRE_PPPP_ 0 -cell $_DLATCH_?_ x");
+
+ run(stringf("techmap -map +/quicklogic/%s_cells_map.v -map +/quicklogic/%s_ffs_map.v", family.c_str(), family.c_str()));
+
+ run("opt_expr -mux_undef");
+ }
+
+ if (check_label("map_luts")) {
+ run(stringf("techmap -map +/quicklogic/%s_latches_map.v", family.c_str()));
+ if (abc9) {
+ run("read_verilog -lib -specify -icells +/quicklogic/abc9_model.v");
+ run("techmap -map +/quicklogic/abc9_map.v");
+ run("abc9 -maxlut 4 -dff");
+ run("techmap -map +/quicklogic/abc9_unmap.v");
+ } else {
+ run("abc -luts 1,2,2,4 -dress");
+ }
+ run("clean");
+ }
+
+ if (check_label("map_cells")) {
+ run(stringf("techmap -map +/quicklogic/%s_lut_map.v", family.c_str()));
+ run("clean");
+ }
+
+ if (check_label("check")) {
+ run("autoname");
+ run("hierarchy -check");
+ run("stat");
+ run("check -noinit");
+ }
+
+ if (check_label("iomap")) {
+ run("clkbufmap -inpad ckpad Q:P");
+ run("iopadmap -bits -outpad outpad A:P -inpad inpad Q:P -tinoutpad bipad EN:Q:A:P A:top");
+ }
+
+ if (check_label("finalize")) {
+ run("setundef -zero -params -undriven");
+ run("hilomap -hicell logic_1 A -locell logic_0 A -singleton A:top");
+ run("opt_clean -purge");
+ run("check");
+ run("blackbox =A:whitebox");
+ }
+
+ if (check_label("blif")) {
+ if (!blif_file.empty() || help_mode) {
+ run(stringf("write_blif -attr -param %s %s", top_opt.c_str(), blif_file.c_str()));
+ }
+ }
+
+ if (check_label("verilog")) {
+ if (!verilog_file.empty() || help_mode) {
+ run(stringf("write_verilog -noattr -nohex %s", help_mode ? "<file-name>" : verilog_file.c_str()));
+ }
+ }
+ }
+
+} SynthQuicklogicPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/techlibs/sf2/arith_map.v b/techlibs/sf2/arith_map.v
index 462d3ce50..f16b1abb8 100644
--- a/techlibs/sf2/arith_map.v
+++ b/techlibs/sf2/arith_map.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/sf2/cells_sim.v b/techlibs/sf2/cells_sim.v
index eff57a655..4b57bad7b 100644
--- a/techlibs/sf2/cells_sim.v
+++ b/techlibs/sf2/cells_sim.v
@@ -1,20 +1,20 @@
// https://coredocs.s3.amazonaws.com/Libero/12_0_0/Tool/sf2_mlg.pdf
-module ADD2 (
+module AND2 (
input A, B,
output Y
);
assign Y = A & B;
endmodule
-module ADD3 (
+module AND3 (
input A, B, C,
output Y
);
assign Y = A & B & C;
endmodule
-module ADD4 (
+module AND4 (
input A, B, C, D,
output Y
);
diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc
index a0061ebd0..8d78a6097 100644
--- a/techlibs/sf2/synth_sf2.cc
+++ b/techlibs/sf2/synth_sf2.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
@@ -228,6 +228,7 @@ struct SynthSf2Pass : public ScriptPass
run("hierarchy -check");
run("stat");
run("check -noinit");
+ run("blackbox =A:whitebox");
}
if (check_label("edif"))
diff --git a/techlibs/xilinx/abc9_model.v b/techlibs/xilinx/abc9_model.v
index db44ff00b..3958a2bf0 100644
--- a/techlibs/xilinx/abc9_model.v
+++ b/techlibs/xilinx/abc9_model.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/techlibs/xilinx/arith_map.v b/techlibs/xilinx/arith_map.v
index 63be7563e..1282f564c 100644
--- a/techlibs/xilinx/arith_map.v
+++ b/techlibs/xilinx/arith_map.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v
index ec4635ac6..2b8eade2f 100644
--- a/techlibs/xilinx/cells_map.v
+++ b/techlibs/xilinx/cells_map.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -359,11 +359,3 @@ module \$__XILINX_MUXF78 (O, I0, I1, I2, I3, S0, S1);
else
MUXF8 mux8 (.I0(T0), .I1(T1), .S(S1), .O(O));
endmodule
-
-module \$__XILINX_TINOUTPAD (input I, OE, output O, inout IO);
- IOBUF _TECHMAP_REPLACE_ (.I(I), .O(O), .T(~OE), .IO(IO));
-endmodule
-
-module \$__XILINX_TOUTPAD (input I, OE, output O);
- OBUFT _TECHMAP_REPLACE_ (.I(I), .O(O), .T(~OE));
-endmodule
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index a079f1c95..ee5a89e22 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/xilinx/ff_map.v b/techlibs/xilinx/ff_map.v
index 45d202294..2079fd99a 100644
--- a/techlibs/xilinx/ff_map.v
+++ b/techlibs/xilinx/ff_map.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/xilinx/lut_map.v b/techlibs/xilinx/lut_map.v
index 2ab6075f1..30d7d8014 100644
--- a/techlibs/xilinx/lut_map.v
+++ b/techlibs/xilinx/lut_map.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/techlibs/xilinx/mux_map.v b/techlibs/xilinx/mux_map.v
index bb31d21ec..f49834491 100644
--- a/techlibs/xilinx/mux_map.v
+++ b/techlibs/xilinx/mux_map.v
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index 0adec57a2..6a060c8fe 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
* (C) 2019 Eddie Hung <eddie@fpgeh.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -558,9 +558,10 @@ struct SynthXilinxPass : public ScriptPass
}
if (check_label("map_cells")) {
- // Needs to be done before logic optimization, so that inverters (OE vs T) are handled.
+ // Needs to be done before logic optimization, so that inverters (inserted
+ // here because of negative-polarity output enable) are handled.
if (help_mode || !noiopad)
- run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad $__XILINX_TOUTPAD OE:I:O -tinoutpad $__XILINX_TINOUTPAD OE:O:I:IO A:top", "(skip if '-noiopad')");
+ run("iopadmap -bits -outpad OBUF I:O -inpad IBUF O:I -toutpad OBUFT ~T:I:O -tinoutpad IOBUF ~T:O:I:IO A:top", "(skip if '-noiopad')");
std::string techmap_args = "-map +/techmap.v -map +/xilinx/cells_map.v";
if (widemux > 0)
techmap_args += stringf(" -D MIN_MUX_INPUTS=%d", widemux);
@@ -662,6 +663,7 @@ struct SynthXilinxPass : public ScriptPass
run("hierarchy -check");
run("stat -tech xilinx");
run("check -noinit");
+ run("blackbox =A:whitebox");
}
if (check_label("edif")) {
@@ -671,7 +673,7 @@ struct SynthXilinxPass : public ScriptPass
if (check_label("blif")) {
if (!blif_file.empty() || help_mode)
- run(stringf("write_blif %s", edif_file.c_str()));
+ run(stringf("write_blif %s", blif_file.c_str()));
}
}
} SynthXilinxPass;
diff --git a/techlibs/xilinx/xc7_brams_map.v b/techlibs/xilinx/xc7_brams_map.v
index 2b6ad0da6..982a5a07e 100644
--- a/techlibs/xilinx/xc7_brams_map.v
+++ b/techlibs/xilinx/xc7_brams_map.v
@@ -16,8 +16,9 @@ module \$__XILINX_RAMB36_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA,
input [71:0] B1DATA;
input [7:0] B1EN;
- wire [15:0] A1ADDR_16 = {A1ADDR, 6'b0};
- wire [15:0] B1ADDR_16 = {B1ADDR, 6'b0};
+ // Set highest address bit to 1, as stated in UG473 (v1.14) July 3, 2019
+ wire [15:0] A1ADDR_16 = {1'b1, A1ADDR, 6'b0};
+ wire [15:0] B1ADDR_16 = {1'b1, B1ADDR, 6'b0};
wire [7:0] DIP, DOP;
wire [63:0] DI, DO;
@@ -153,8 +154,9 @@ module \$__XILINX_RAMB36_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA,
input [CFG_DBITS-1:0] B1DATA;
input [CFG_ENABLE_B-1:0] B1EN;
- wire [15:0] A1ADDR_16 = A1ADDR << (15 - CFG_ABITS);
- wire [15:0] B1ADDR_16 = B1ADDR << (15 - CFG_ABITS);
+ // Set highest address bit to 1, as stated in UG473 (v1.14) July 3, 2019
+ wire [15:0] A1ADDR_16 = {1'b1, A1ADDR} << (15 - CFG_ABITS);
+ wire [15:0] B1ADDR_16 = {1'b1, B1ADDR} << (15 - CFG_ABITS);
wire [7:0] B1EN_8 = B1EN;
wire [3:0] DIP, DOP;
diff --git a/techlibs/xilinx/xilinx_dffopt.cc b/techlibs/xilinx/xilinx_dffopt.cc
index 598f1b216..677082916 100644
--- a/techlibs/xilinx/xilinx_dffopt.cc
+++ b/techlibs/xilinx/xilinx_dffopt.cc
@@ -1,7 +1,7 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
- * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.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
diff --git a/tests/arch/anlogic/blockram.ys b/tests/arch/anlogic/blockram.ys
new file mode 100644
index 000000000..da23409ba
--- /dev/null
+++ b/tests/arch/anlogic/blockram.ys
@@ -0,0 +1,13 @@
+read_verilog ../common/blockram.v
+hierarchy -top sync_ram_sp
+proc
+memory -nomap
+equiv_opt -run :prove -map +/anlogic/cells_sim.v synth_anlogic
+memory
+opt -full
+
+design -load postopt
+cd sync_ram_sp
+
+select -assert-count 1 t:EG_PHY_BRAM
+select -assert-none t:EG_PHY_BRAM %% t:* %D
diff --git a/tests/arch/anlogic/lutram.ys b/tests/arch/anlogic/lutram.ys
index 9ebb75443..fe6135c73 100644
--- a/tests/arch/anlogic/lutram.ys
+++ b/tests/arch/anlogic/lutram.ys
@@ -2,7 +2,7 @@ read_verilog ../common/lutram.v
hierarchy -top lutram_1w1r
proc
memory -nomap
-equiv_opt -run :prove -map +/anlogic/cells_sim.v synth_anlogic
+equiv_opt -run :prove -map +/anlogic/cells_sim.v synth_anlogic -nobram
memory
opt -full
@@ -13,9 +13,8 @@ miter -equiv -flatten -make_assert -make_outputs gold gate miter
design -load postopt
cd lutram_1w1r
-select -assert-count 8 t:AL_MAP_LUT2
-select -assert-count 8 t:AL_MAP_LUT4
-select -assert-count 8 t:AL_MAP_LUT5
-select -assert-count 36 t:AL_MAP_SEQ
+select -assert-count 4 t:AL_MAP_LUT3
+select -assert-count 8 t:AL_MAP_LUT6
+select -assert-count 8 t:AL_MAP_SEQ
select -assert-count 8 t:EG_LOGIC_DRAM16X4 #Why not AL_LOGIC_BRAM?
-select -assert-none t:AL_MAP_LUT2 t:AL_MAP_LUT4 t:AL_MAP_LUT5 t:AL_MAP_SEQ t:EG_LOGIC_DRAM16X4 %% t:* %D
+select -assert-none t:AL_MAP_LUT3 t:AL_MAP_LUT6 t:AL_MAP_SEQ t:EG_LOGIC_DRAM16X4 %% t:* %D
diff --git a/tests/arch/common/adffs.v b/tests/arch/common/adffs.v
index 576bd81a6..966e7c2b8 100644
--- a/tests/arch/common/adffs.v
+++ b/tests/arch/common/adffs.v
@@ -1,7 +1,9 @@
module adff( input d, clk, clr, output reg q );
+`ifndef NO_INIT
initial begin
q = 0;
end
+`endif
always @( posedge clk, posedge clr )
if ( clr )
q <= 1'b0;
@@ -10,9 +12,11 @@ module adff( input d, clk, clr, output reg q );
endmodule
module adffn( input d, clk, clr, output reg q );
+`ifndef NO_INIT
initial begin
q = 0;
end
+`endif
always @( posedge clk, negedge clr )
if ( !clr )
q <= 1'b0;
@@ -21,9 +25,11 @@ module adffn( input d, clk, clr, output reg q );
endmodule
module dffs( input d, clk, pre, clr, output reg q );
+`ifndef NO_INIT
initial begin
q = 0;
end
+`endif
always @( posedge clk )
if ( pre )
q <= 1'b1;
@@ -32,9 +38,11 @@ module dffs( input d, clk, pre, clr, output reg q );
endmodule
module ndffnr( input d, clk, pre, clr, output reg q );
+`ifndef NO_INIT
initial begin
q = 0;
end
+`endif
always @( negedge clk )
if ( !clr )
q <= 1'b0;
diff --git a/tests/arch/common/counter.v b/tests/arch/common/counter.v
index 9746fd701..1e0a13dc9 100644
--- a/tests/arch/common/counter.v
+++ b/tests/arch/common/counter.v
@@ -1,11 +1,11 @@
-module top ( out, clk, reset );
- output [7:0] out;
- input clk, reset;
- reg [7:0] out;
-
- always @(posedge clk, posedge reset)
- if (reset)
- out <= 8'b0;
- else
- out <= out + 1;
-endmodule
+module top ( out, clk, reset );
+ output [7:0] out;
+ input clk, reset;
+ reg [7:0] out;
+
+ always @(posedge clk, posedge reset)
+ if (reset)
+ out <= 8'b0;
+ else
+ out <= out + 1;
+endmodule
diff --git a/tests/arch/common/dffs.v b/tests/arch/common/dffs.v
index 636252d16..0c607af50 100644
--- a/tests/arch/common/dffs.v
+++ b/tests/arch/common/dffs.v
@@ -4,9 +4,11 @@ module dff ( input d, clk, output reg q );
endmodule
module dffe( input d, clk, en, output reg q );
+`ifndef NO_INIT
initial begin
q = 0;
end
+`endif
always @( posedge clk )
if ( en )
q <= d;
diff --git a/tests/arch/common/fsm.v b/tests/arch/common/fsm.v
index 9d3fbb64a..cf1c21a58 100644
--- a/tests/arch/common/fsm.v
+++ b/tests/arch/common/fsm.v
@@ -1,51 +1,51 @@
- module fsm ( clock, reset, req_0, req_1, gnt_0, gnt_1 );
- input clock,reset,req_0,req_1;
- output gnt_0,gnt_1;
- wire clock,reset,req_0,req_1;
- reg gnt_0,gnt_1;
-
- parameter SIZE = 3;
- parameter IDLE = 3'b001;
- parameter GNT0 = 3'b010;
- parameter GNT1 = 3'b100;
- parameter GNT2 = 3'b101;
-
- reg [SIZE-1:0] state;
- reg [SIZE-1:0] next_state;
-
- always @ (posedge clock)
- begin : FSM
- if (reset == 1'b1) begin
- state <= #1 IDLE;
- gnt_0 <= 0;
- gnt_1 <= 0;
- end
- else
- case(state)
- IDLE : if (req_0 == 1'b1) begin
- state <= #1 GNT0;
- gnt_0 <= 1;
- end else if (req_1 == 1'b1) begin
- gnt_1 <= 1;
- state <= #1 GNT0;
- end else begin
- state <= #1 IDLE;
- end
- GNT0 : if (req_0 == 1'b1) begin
- state <= #1 GNT0;
- end else begin
- gnt_0 <= 0;
- state <= #1 IDLE;
- end
- GNT1 : if (req_1 == 1'b1) begin
- state <= #1 GNT2;
- gnt_1 <= req_0;
- end
- GNT2 : if (req_0 == 1'b1) begin
- state <= #1 GNT1;
- gnt_1 <= req_1;
- end
- default : state <= #1 IDLE;
- endcase
- end
-endmodule
+ module fsm ( clock, reset, req_0, req_1, gnt_0, gnt_1 );
+ input clock,reset,req_0,req_1;
+ output gnt_0,gnt_1;
+ wire clock,reset,req_0,req_1;
+ reg gnt_0,gnt_1;
+
+ parameter SIZE = 3;
+ parameter IDLE = 3'b001;
+ parameter GNT0 = 3'b010;
+ parameter GNT1 = 3'b100;
+ parameter GNT2 = 3'b101;
+
+ reg [SIZE-1:0] state;
+ reg [SIZE-1:0] next_state;
+
+ always @ (posedge clock)
+ begin : FSM
+ if (reset == 1'b1) begin
+ state <= #1 IDLE;
+ gnt_0 <= 0;
+ gnt_1 <= 0;
+ end
+ else
+ case(state)
+ IDLE : if (req_0 == 1'b1) begin
+ state <= #1 GNT0;
+ gnt_0 <= 1;
+ end else if (req_1 == 1'b1) begin
+ gnt_1 <= 1;
+ state <= #1 GNT0;
+ end else begin
+ state <= #1 IDLE;
+ end
+ GNT0 : if (req_0 == 1'b1) begin
+ state <= #1 GNT0;
+ end else begin
+ gnt_0 <= 0;
+ state <= #1 IDLE;
+ end
+ GNT1 : if (req_1 == 1'b1) begin
+ state <= #1 GNT2;
+ gnt_1 <= req_0;
+ end
+ GNT2 : if (req_0 == 1'b1) begin
+ state <= #1 GNT1;
+ gnt_1 <= req_1;
+ end
+ default : state <= #1 IDLE;
+ endcase
+ end
+endmodule
diff --git a/tests/arch/common/shifter.v b/tests/arch/common/shifter.v
index cace3b588..06e63c9af 100644
--- a/tests/arch/common/shifter.v
+++ b/tests/arch/common/shifter.v
@@ -1,11 +1,17 @@
-module top(out, clk, in);
- output [7:0] out;
- input signed clk, in;
- reg signed [7:0] out = 0;
-
- always @(posedge clk)
- begin
- out <= out >> 1;
- out[7] <= in;
- end
-endmodule
+module top(out, clk, in);
+ output [7:0] out;
+ input signed clk, in;
+ reg signed [7:0] out;
+
+`ifndef NO_INIT
+ initial begin
+ out = 0;
+ end
+`endif
+
+ always @(posedge clk)
+ begin
+ out <= out >> 1;
+ out[7] <= in;
+ end
+endmodule
diff --git a/tests/arch/ecp5/bug2731.ys b/tests/arch/ecp5/bug2731.ys
new file mode 100644
index 000000000..c609cea3b
--- /dev/null
+++ b/tests/arch/ecp5/bug2731.ys
@@ -0,0 +1,7 @@
+read_verilog -icells <<EOF
+module top(input c, r, input [1:0] d, output reg [1:0] q);
+TRELLIS_FF #(.REGSET("SET")) ff1(.CLK(c), .LSR(r), .DI(d[0]), .Q(q[0]));
+TRELLIS_FF #(.REGSET("SET")) ff2(.CLK(c), .LSR(r), .DI(d[1]), .Q(q[1]));
+endmodule
+EOF
+synth_ecp5 -abc9 -dff
diff --git a/tests/arch/ecp5/lutram.ys b/tests/arch/ecp5/lutram.ys
index e1ae7abd5..9bef37c68 100644
--- a/tests/arch/ecp5/lutram.ys
+++ b/tests/arch/ecp5/lutram.ys
@@ -11,9 +11,9 @@ sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs mite
design -load postopt
cd lutram_1w1r
-select -assert-count 24 t:L6MUX21
-select -assert-count 71 t:LUT4
-select -assert-count 32 t:PFUMX
+select -assert-count 8 t:L6MUX21
+select -assert-count 36 t:LUT4
+select -assert-count 16 t:PFUMX
select -assert-count 8 t:TRELLIS_DPR16X4
-select -assert-count 35 t:TRELLIS_FF
+select -assert-count 8 t:TRELLIS_FF
select -assert-none t:L6MUX21 t:LUT4 t:PFUMX t:TRELLIS_DPR16X4 t:TRELLIS_FF %% t:* %D
diff --git a/tests/arch/ecp5/memories.ys b/tests/arch/ecp5/memories.ys
index f55bf01d2..44651ba25 100644
--- a/tests/arch/ecp5/memories.ys
+++ b/tests/arch/ecp5/memories.ys
@@ -1,328 +1,379 @@
# ================================ RAM ================================
# RAM bits <= 18K; Data width <= 36; Address width <= 9: -> PDPW16KD
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 36 sync_ram_sdp
+hierarchy -top sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:PDPW16KD
## With parameters
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+hierarchy -top sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:PDPW16KD # too inefficient
select -assert-count 9 t:TRELLIS_DPR16X4
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "block_ram" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:PDPW16KD
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "Block_RAM" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:PDPW16KD # any case works
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set ram_block 1 m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:PDPW16KD
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "registers" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:PDPW16KD # requested FFRAM explicitly
select -assert-count 180 t:TRELLIS_FF
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set logic_block 1 m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:PDPW16KD # requested FFRAM explicitly
select -assert-count 180 t:TRELLIS_FF
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_romstyle "ebr" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
-select -assert-count 1 t:$mem # requested BROM but this is a RAM
+select -assert-count 1 t:$mem_v2 # requested BROM but this is a RAM
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set rom_block 1 m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
-select -assert-count 1 t:$mem # requested BROM but this is a RAM
+select -assert-count 1 t:$mem_v2 # requested BROM but this is a RAM
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "block_ram" m:memory
synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp
-select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
+select -assert-count 1 t:$mem_v2 # requested BRAM but BRAM is disabled
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set ram_block 1 m:memory
synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp
-select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
+select -assert-count 1 t:$mem_v2 # requested BRAM but BRAM is disabled
# RAM bits <= 18K; Data width <= 18; Address width <= 10: -> DP16KD
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 18 sync_ram_sdp
+hierarchy -top sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 11 -set DATA_WIDTH 9 sync_ram_sdp
+hierarchy -top sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 12 -set DATA_WIDTH 4 sync_ram_sdp
+hierarchy -top sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 13 -set DATA_WIDTH 2 sync_ram_sdp
+hierarchy -top sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 14 -set DATA_WIDTH 1 sync_ram_sdp
+hierarchy -top sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD
## With parameters
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+hierarchy -top sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:DP16KD # too inefficient
select -assert-count 5 t:TRELLIS_DPR16X4
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "block_ram" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "Block_RAM" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD # any case works
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set ram_block 1 m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:DP16KD
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "registers" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:DP16KD # requested FFRAM explicitly
select -assert-count 90 t:TRELLIS_FF
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set logic_block 1 m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:DP16KD # requested FFRAM explicitly
select -assert-count 90 t:TRELLIS_FF
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_romstyle "ebr" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
-select -assert-count 1 t:$mem # requested BROM but this is a RAM
+select -assert-count 1 t:$mem_v2 # requested BROM but this is a RAM
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set rom_block 1 m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
-select -assert-count 1 t:$mem # requested BROM but this is a RAM
+select -assert-count 1 t:$mem_v2 # requested BROM but this is a RAM
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "block_ram" m:memory
synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp
-select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
+select -assert-count 1 t:$mem_v2 # requested BRAM but BRAM is disabled
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set ram_block 1 m:memory
synth_ecp5 -top sync_ram_sdp -nobram; cd sync_ram_sdp
-select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
+select -assert-count 1 t:$mem_v2 # requested BRAM but BRAM is disabled
# RAM bits <= 64; Data width <= 4; Address width <= 4: -> DPR16X4
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
+hierarchy -top sync_ram_sdp
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:TRELLIS_DPR16X4
## With parameters
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "distributed" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:TRELLIS_DPR16X4
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "registers" m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:TRELLIS_DPR16X4 # requested FFRAM explicitly
select -assert-count 68 t:TRELLIS_FF
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set logic_block 1 m:memory
synth_ecp5 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:TRELLIS_DPR16X4 # requested FFRAM explicitly
select -assert-count 68 t:TRELLIS_FF
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 4 -set DATA_WIDTH 4 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "distributed" m:memory
synth_ecp5 -top sync_ram_sdp -nolutram; cd sync_ram_sdp
-select -assert-count 1 t:$mem # requested LUTRAM but LUTRAM is disabled
+select -assert-count 1 t:$mem_v2 # requested LUTRAM but LUTRAM is disabled
# ================================ ROM ================================
# ROM bits <= 18K; Data width <= 36; Address width <= 9: -> PDPW16KD
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 36 sync_rom
+hierarchy -top sync_rom
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:PDPW16KD
## With parameters
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 36 sync_rom
+hierarchy -top sync_rom
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 0 t:PDPW16KD # too inefficient
select -assert-min 18 t:LUT4
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
+hierarchy -top sync_rom
setattr -set syn_romstyle "ebr" m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:PDPW16KD
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
+hierarchy -top sync_rom
setattr -set rom_block 1 m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:PDPW16KD
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 36 sync_rom
+hierarchy -top sync_rom
setattr -set syn_romstyle "logic" m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 0 t:PDPW16KD # requested LUTROM explicitly
select -assert-min 18 t:LUT4
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 36 sync_rom
+hierarchy -top sync_rom
setattr -set logic_block 1 m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 0 t:PDPW16KD # requested LUTROM explicitly
select -assert-min 18 t:LUT4
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
+hierarchy -top sync_rom
setattr -set syn_ramstyle "block_ram" m:memory
synth_ecp5 -top sync_rom; cd sync_rom
-select -assert-count 1 t:$mem # requested BRAM but this is a ROM
+select -assert-count 1 t:$mem_v2 # requested BRAM but this is a ROM
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
+hierarchy -top sync_rom
setattr -set ram_block 1 m:memory
synth_ecp5 -top sync_rom; cd sync_rom
-select -assert-count 1 t:$mem # requested BRAM but this is a ROM
+select -assert-count 1 t:$mem_v2 # requested BRAM but this is a ROM
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
+hierarchy -top sync_rom
setattr -set syn_ramstyle "block_rom" m:memory
synth_ecp5 -top sync_rom -nobram; cd sync_rom
-select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
+select -assert-count 1 t:$mem_v2 # requested BROM but BRAM is disabled
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 36 sync_rom
+hierarchy -top sync_rom
setattr -set rom_block 1 m:memory
synth_ecp5 -top sync_rom -nobram; cd sync_rom
-select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
+select -assert-count 1 t:$mem_v2 # requested BROM but BRAM is disabled
# ROM bits <= 18K; Data width <= 18; Address width <= 10: -> DP16KD
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 18 sync_rom
+hierarchy -top sync_rom
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:DP16KD
## With parameters
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 18 sync_rom
+hierarchy -top sync_rom
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 0 t:DP16KD # too inefficient
select -assert-min 9 t:LUT4
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
+hierarchy -top sync_rom
setattr -set syn_romstyle "ebr" m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:DP16KD
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
+hierarchy -top sync_rom
setattr -set rom_block 1 m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 1 t:DP16KD
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 18 sync_rom
+hierarchy -top sync_rom
setattr -set syn_romstyle "logic" m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 0 t:DP16KD # requested LUTROM explicitly
select -assert-min 9 t:LUT4
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 3 -set DATA_WIDTH 18 sync_rom
+hierarchy -top sync_rom
setattr -set logic_block 1 m:memory
synth_ecp5 -top sync_rom; cd sync_rom
select -assert-count 0 t:DP16KD # requested LUTROM explicitly
select -assert-min 9 t:LUT4
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
+hierarchy -top sync_rom
setattr -set syn_ramstyle "block_ram" m:memory
synth_ecp5 -top sync_rom; cd sync_rom
-select -assert-count 1 t:$mem # requested BRAM but this is a ROM
+select -assert-count 1 t:$mem_v2 # requested BRAM but this is a ROM
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
+hierarchy -top sync_rom
setattr -set ram_block 1 m:memory
synth_ecp5 -top sync_rom; cd sync_rom
-select -assert-count 1 t:$mem # requested BRAM but this is a ROM
+select -assert-count 1 t:$mem_v2 # requested BRAM but this is a ROM
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
+hierarchy -top sync_rom
setattr -set syn_ramstyle "block_rom" m:memory
synth_ecp5 -top sync_rom -nobram; cd sync_rom
-select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
+select -assert-count 1 t:$mem_v2 # requested BROM but BRAM is disabled
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 18 sync_rom
+hierarchy -top sync_rom
setattr -set rom_block 1 m:memory
synth_ecp5 -top sync_rom -nobram; cd sync_rom
-select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
+select -assert-count 1 t:$mem_v2 # requested BROM but BRAM is disabled
diff --git a/tests/arch/ecp5/mux.ys b/tests/arch/ecp5/mux.ys
index 92463aa32..db63dda5f 100644
--- a/tests/arch/ecp5/mux.ys
+++ b/tests/arch/ecp5/mux.ys
@@ -15,9 +15,9 @@ proc
equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux4 # Constrain all select calls below inside the top module
-select -assert-count 1 t:L6MUX21
-select -assert-count 4 t:LUT4
-select -assert-count 2 t:PFUMX
+select -assert-max 1 t:L6MUX21
+select -assert-max 4 t:LUT4
+select -assert-max 2 t:PFUMX
select -assert-none t:LUT4 t:L6MUX21 t:PFUMX %% t:* %D
@@ -27,9 +27,9 @@ proc
equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux8 # Constrain all select calls below inside the top module
-select -assert-count 1 t:L6MUX21
-select -assert-count 7 t:LUT4
-select -assert-count 2 t:PFUMX
+select -assert-max 1 t:L6MUX21
+select -assert-max 7 t:LUT4
+select -assert-max 2 t:PFUMX
select -assert-none t:LUT4 t:L6MUX21 t:PFUMX %% t:* %D
@@ -39,8 +39,8 @@ proc
equiv_opt -assert -map +/ecp5/cells_sim.v synth_ecp5 # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux16 # Constrain all select calls below inside the top module
-select -assert-count 8 t:L6MUX21
-select -assert-count 26 t:LUT4
-select -assert-count 12 t:PFUMX
+select -assert-max 12 t:L6MUX21
+select -assert-max 34 t:LUT4
+select -assert-max 17 t:PFUMX
select -assert-none t:LUT4 t:L6MUX21 t:PFUMX %% t:* %D
diff --git a/tests/arch/gatemate/.gitignore b/tests/arch/gatemate/.gitignore
new file mode 100644
index 000000000..9a71dca69
--- /dev/null
+++ b/tests/arch/gatemate/.gitignore
@@ -0,0 +1,4 @@
+*.log
+/run-test.mk
++*_synth.v
++*_testbench
diff --git a/tests/arch/gatemate/add_sub.ys b/tests/arch/gatemate/add_sub.ys
new file mode 100644
index 000000000..bf261ba5a
--- /dev/null
+++ b/tests/arch/gatemate/add_sub.ys
@@ -0,0 +1,9 @@
+read_verilog ../common/add_sub.v
+hierarchy -top top
+proc
+equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+select -assert-count 8 t:CC_ADDF
+select -assert-max 4 t:CC_LUT1
+select -assert-none t:CC_ADDF t:CC_LUT1 %% t:* %D
diff --git a/tests/arch/gatemate/adffs.ys b/tests/arch/gatemate/adffs.ys
new file mode 100644
index 000000000..b2ded6e9d
--- /dev/null
+++ b/tests/arch/gatemate/adffs.ys
@@ -0,0 +1,43 @@
+read_verilog -D NO_INIT ../common/adffs.v
+design -save read
+
+hierarchy -top adff
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd adff # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_DFF
+select -assert-none t:CC_BUFG t:CC_DFF %% t:* %D
+
+design -load read
+hierarchy -top adffn
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd adffn # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_DFF
+select -assert-none t:CC_BUFG t:CC_DFF %% t:* %D
+
+design -load read
+hierarchy -top dffs
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd dffs # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_DFF
+select -assert-max 1 t:CC_LUT2
+select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D
+
+design -load read
+hierarchy -top ndffnr
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd ndffnr # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_DFF
+select -assert-max 1 t:CC_LUT2
+select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 %% t:* %D
diff --git a/tests/arch/gatemate/counter.ys b/tests/arch/gatemate/counter.ys
new file mode 100644
index 000000000..77ed858b3
--- /dev/null
+++ b/tests/arch/gatemate/counter.ys
@@ -0,0 +1,12 @@
+read_verilog ../common/counter.v
+hierarchy -top top
+proc
+flatten
+equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+
+select -assert-count 8 t:CC_ADDF
+select -assert-count 1 t:CC_BUFG
+select -assert-count 8 t:CC_DFF
+select -assert-none t:CC_ADDF t:CC_BUFG t:CC_DFF %% t:* %D
diff --git a/tests/arch/gatemate/dffs.ys b/tests/arch/gatemate/dffs.ys
new file mode 100644
index 000000000..022322419
--- /dev/null
+++ b/tests/arch/gatemate/dffs.ys
@@ -0,0 +1,21 @@
+read_verilog -D NO_INIT ../common/dffs.v
+design -save read
+
+hierarchy -top dff
+proc
+equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd dff # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_DFF
+select -assert-none t:CC_BUFG t:CC_DFF %% t:* %D
+
+design -load read
+hierarchy -top dffe
+proc
+equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd dffe # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_DFF
+select -assert-none t:CC_BUFG t:CC_DFF %% t:* %D
diff --git a/tests/arch/gatemate/fsm.ys b/tests/arch/gatemate/fsm.ys
new file mode 100644
index 000000000..6b43ead7a
--- /dev/null
+++ b/tests/arch/gatemate/fsm.ys
@@ -0,0 +1,20 @@
+read_verilog ../common/fsm.v
+hierarchy -top fsm
+proc
+flatten
+
+equiv_opt -run :prove -map +/gatemate/cells_sim.v synth_gatemate -noiopad
+async2sync
+miter -equiv -make_assert -flatten gold gate miter
+stat
+sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter
+
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd fsm # Constrain all select calls below inside the top module
+
+select -assert-count 1 t:CC_BUFG
+select -assert-count 6 t:CC_DFF
+select -assert-max 5 t:CC_LUT2
+select -assert-max 4 t:CC_LUT3
+select -assert-max 9 t:CC_LUT4
+select -assert-none t:CC_BUFG t:CC_DFF t:CC_LUT2 t:CC_LUT3 t:CC_LUT4 %% t:* %D
diff --git a/tests/arch/gatemate/latches.ys b/tests/arch/gatemate/latches.ys
new file mode 100644
index 000000000..5f64c6db5
--- /dev/null
+++ b/tests/arch/gatemate/latches.ys
@@ -0,0 +1,29 @@
+read_verilog ../common/latches.v
+design -save read
+
+hierarchy -top latchp
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd latchp # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_DLT
+select -assert-none t:CC_DLT %% t:* %D
+
+design -load read
+hierarchy -top latchn
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd latchn # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_DLT
+select -assert-none t:CC_DLT %% t:* %D
+
+design -load read
+hierarchy -top latchsr
+proc
+equiv_opt -async2sync -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd latchsr # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_DLT
+select -assert-max 2 t:CC_LUT3
+select -assert-none t:CC_DLT t:CC_LUT3 %% t:* %D
diff --git a/tests/arch/gatemate/logic.ys b/tests/arch/gatemate/logic.ys
new file mode 100644
index 000000000..026406bc8
--- /dev/null
+++ b/tests/arch/gatemate/logic.ys
@@ -0,0 +1,10 @@
+read_verilog ../common/logic.v
+hierarchy -top top
+proc
+equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+select -assert-max 1 t:CC_LUT1
+select -assert-max 6 t:CC_LUT2
+select -assert-max 2 t:CC_LUT4
+select -assert-none t:CC_LUT1 t:CC_LUT2 t:CC_LUT4 %% t:* %D
diff --git a/tests/arch/gatemate/memory.ys b/tests/arch/gatemate/memory.ys
new file mode 100644
index 000000000..e919920f8
--- /dev/null
+++ b/tests/arch/gatemate/memory.ys
@@ -0,0 +1,34 @@
+# 512 x 40 bit -> CC_BRAM_20K SDP RAM
+read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 40 sync_ram_sdp
+synth_gatemate -top sync_ram_sdp -noiopad
+cd sync_ram_sdp
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_BRAM_20K
+
+# 512 x 80 bit -> CC_BRAM_40K SDP RAM
+design -reset
+read_verilog ../common/blockram.v
+chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 80 sync_ram_sdp
+synth_gatemate -top sync_ram_sdp -noiopad
+cd sync_ram_sdp
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_BRAM_40K
+
+# 512 x 40 bit -> CC_BRAM_20K SDP ROM
+design -reset
+read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 40 sync_rom
+synth_gatemate -top sync_rom -noiopad
+cd sync_rom
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_BRAM_20K
+
+# 512 x 80 bit -> CC_BRAM_40K SDP ROM
+design -reset
+read_verilog ../common/blockrom.v
+chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 80 sync_rom
+synth_gatemate -top sync_rom -noiopad
+cd sync_rom
+select -assert-count 1 t:CC_BUFG
+select -assert-count 1 t:CC_BRAM_40K
diff --git a/tests/arch/gatemate/mul.v b/tests/arch/gatemate/mul.v
new file mode 100644
index 000000000..55e8f9006
--- /dev/null
+++ b/tests/arch/gatemate/mul.v
@@ -0,0 +1,79 @@
+
+module mul_plain(a, b, p);
+
+ parameter M = 6;
+ parameter N = 6;
+
+ input wire [M-1:0] a;
+ input wire [N-1:0] b;
+ output wire [M+N-1:0] p;
+
+ assign p = a * b;
+
+endmodule
+
+module mul_signed_async (clk, rst, en, a, b, p);
+
+ parameter M = 8;
+ parameter N = 6;
+
+ input wire signed clk, rst, en;
+ input wire signed [M-1:0] a;
+ input wire signed [N-1:0] b;
+ output reg signed [M+N-1:0] p;
+
+ reg signed [M-1:0] a_reg;
+ reg signed [N-1:0] b_reg;
+
+ // signed M*N multiplier with
+ // - input and output pipeline registers
+ // - asynchronous reset (active high)
+ // - clock enable (active high)
+ always @(posedge clk or posedge rst)
+ begin
+ if (rst) begin
+ a_reg <= 0;
+ b_reg <= 0;
+ p <= 0;
+ end
+ else if (en) begin
+ a_reg <= a;
+ b_reg <= b;
+ p <= a_reg * b_reg;
+ end
+ end
+
+endmodule
+
+module mul_unsigned_sync (clk, rst, en, a, b, p);
+
+ parameter M = 6;
+ parameter N = 3;
+
+ input wire clk, rst, en;
+ input wire [M-1:0] a;
+ input wire [N-1:0] b;
+ output reg [M+N-1:0] p;
+
+ reg [M-1:0] a_reg;
+ reg [N-1:0] b_reg;
+
+ // unsigned M*N multiplier with
+ // - input and output pipeline registers
+ // - synchronous reset (active high)
+ // - clock enable (active high)
+ always @(posedge clk)
+ begin
+ if (rst) begin
+ a_reg <= 0;
+ b_reg <= 0;
+ p <= 0;
+ end
+ else if (en) begin
+ a_reg <= a;
+ b_reg <= b;
+ p <= a_reg * b_reg;
+ end
+ end
+
+endmodule
diff --git a/tests/arch/gatemate/mul.ys b/tests/arch/gatemate/mul.ys
new file mode 100644
index 000000000..ded5fe729
--- /dev/null
+++ b/tests/arch/gatemate/mul.ys
@@ -0,0 +1,33 @@
+read_verilog mul.v
+design -save read
+
+hierarchy -top mul_plain
+proc
+equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mul_plain # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_MULT
+select -assert-none t:CC_MULT %% t:* %D
+
+design -load read
+hierarchy -top mul_signed_async
+proc
+equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mul_signed_async # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_MULT
+select -assert-count 1 t:CC_BUFG
+select -assert-count 28 t:CC_DFF
+select -assert-none t:CC_MULT t:CC_BUFG t:CC_DFF %% t:* %D
+
+design -load read
+hierarchy -top mul_unsigned_sync
+proc
+equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mul_unsigned_sync # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_MULT
+select -assert-count 1 t:CC_BUFG
+select -assert-max 18 t:CC_LUT4
+select -assert-count 18 t:CC_DFF
+select -assert-none t:CC_MULT t:CC_BUFG t:CC_LUT4 t:CC_DFF %% t:* %D
diff --git a/tests/arch/gatemate/mux.ys b/tests/arch/gatemate/mux.ys
new file mode 100644
index 000000000..320ff33d7
--- /dev/null
+++ b/tests/arch/gatemate/mux.ys
@@ -0,0 +1,24 @@
+read_verilog ../common/mux.v
+design -save read
+
+design -load read
+hierarchy -top mux4
+proc
+equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mux4 # Constrain all select calls below inside the top module
+select -assert-max 1 t:CC_LUT2
+select -assert-max 2 t:CC_LUT4
+select -assert-max 1 t:CC_MX2
+select -assert-none t:CC_LUT2 t:CC_LUT4 t:CC_MX2 %% t:* %D
+
+design -load read
+hierarchy -top mux8
+proc
+equiv_opt -assert -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mux8 # Constrain all select calls below inside the top module
+select -assert-max 1 t:CC_LUT3
+select -assert-max 5 t:CC_LUT4
+select -assert-max 1 t:CC_MX2
+select -assert-none t:CC_LUT3 t:CC_LUT4 t:CC_MX2 %% t:* %D
diff --git a/tests/arch/gatemate/run-test.sh b/tests/arch/gatemate/run-test.sh
new file mode 100755
index 000000000..4be4b70ae
--- /dev/null
+++ b/tests/arch/gatemate/run-test.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+set -eu
+source ../../gen-tests-makefile.sh
+run_tests --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'"
diff --git a/tests/arch/gatemate/shifter.ys b/tests/arch/gatemate/shifter.ys
new file mode 100644
index 000000000..0006a298a
--- /dev/null
+++ b/tests/arch/gatemate/shifter.ys
@@ -0,0 +1,10 @@
+read_verilog -D NO_INIT ../common/shifter.v
+hierarchy -top top
+proc
+flatten
+equiv_opt -assert -async2sync -map +/gatemate/cells_sim.v synth_gatemate -noiopad # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+select -assert-count 1 t:CC_BUFG
+select -assert-count 8 t:CC_DFF
+select -assert-none t:CC_BUFG t:CC_DFF %% t:* %D
diff --git a/tests/arch/gatemate/tribuf.ys b/tests/arch/gatemate/tribuf.ys
new file mode 100644
index 000000000..d900fa5e4
--- /dev/null
+++ b/tests/arch/gatemate/tribuf.ys
@@ -0,0 +1,13 @@
+read_verilog ../common/tribuf.v
+hierarchy -top tristate
+proc
+tribuf
+flatten
+synth
+equiv_opt -assert -map +/gatemate/cells_sim.v -map +/simcells.v synth_gatemate # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd tristate # Constrain all select calls below inside the top module
+select -assert-count 2 t:CC_IBUF
+select -assert-max 1 t:CC_LUT1
+select -assert-count 1 t:CC_TOBUF
+select -assert-none t:CC_IBUF t:CC_LUT1 t:CC_TOBUF %% t:* %D
diff --git a/tests/arch/gowin/lutram.ys b/tests/arch/gowin/lutram.ys
index 56f69e7c5..d668783a2 100644
--- a/tests/arch/gowin/lutram.ys
+++ b/tests/arch/gowin/lutram.ys
@@ -7,12 +7,11 @@ memory
opt -full
miter -equiv -flatten -make_assert -make_outputs gold gate miter
-#ERROR: Called with -verify and proof did fail!
-#sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter
+sat -verify -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter
sat -prove-asserts -seq 5 -set-init-zero -show-inputs -show-outputs miter
design -load postopt
cd lutram_1w1r
-select -assert-count 8 t:RAM16S4
+select -assert-count 8 t:RAM16SDP4
# other logic present that is not simple
#select -assert-none t:RAM16S4 %% t:* %D
diff --git a/tests/arch/gowin/tribuf.ys b/tests/arch/gowin/tribuf.ys
index 5855b9d97..eef7e379f 100644
--- a/tests/arch/gowin/tribuf.ys
+++ b/tests/arch/gowin/tribuf.ys
@@ -9,5 +9,6 @@ design -load postopt # load the post-opt design (otherwise equiv_opt loads the p
cd tristate # Constrain all select calls below inside the top module
#Internal cell type used. Need support it.
select -assert-count 1 t:TBUF
+select -assert-count 1 t:LUT1
select -assert-count 2 t:IBUF
-select -assert-none t:TBUF t:IBUF %% t:* %D
+select -assert-none t:TBUF t:IBUF t:LUT1 %% t:* %D \ No newline at end of file
diff --git a/tests/arch/ice40/bug2061.ys b/tests/arch/ice40/bug2061.ys
new file mode 100644
index 000000000..7dd7ee6a3
--- /dev/null
+++ b/tests/arch/ice40/bug2061.ys
@@ -0,0 +1,24 @@
+read_verilog <<EOT
+module top #(
+ parameter integer WIDTH = 12
+)(
+ output reg [WIDTH:0] cnt,
+ input wire clk,
+ input wire rst
+);
+ wire last_n;
+
+ assign last_n = cnt[WIDTH];
+
+ always @(posedge clk or posedge rst)
+ if (rst)
+ cnt <= 0;
+ else
+ cnt <= last_n ? ( cnt + { (WIDTH+1){last_n} } ) : 13'h1aaa;
+
+endmodule
+EOT
+
+synth_ice40
+splitnets
+select -assert-count 12 t:SB_CARRY %co:+[CO] t:SB_LUT4 %ci:+[I3] %i
diff --git a/tests/arch/ice40/memories.ys b/tests/arch/ice40/memories.ys
index c32f12315..4920a45e3 100644
--- a/tests/arch/ice40/memories.ys
+++ b/tests/arch/ice40/memories.ys
@@ -1,167 +1,194 @@
# ================================ RAM ================================
# RAM bits <= 4K; Data width <= 16; Address width <= 11: -> SB_RAM40_4K
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 11 -set DATA_WIDTH 2 sync_ram_sdp
+hierarchy -top sync_ram_sdp
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:SB_RAM40_4K
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 4 sync_ram_sdp
+hierarchy -top sync_ram_sdp
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:SB_RAM40_4K
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 8 sync_ram_sdp
+hierarchy -top sync_ram_sdp
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:SB_RAM40_4K
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 8 -set DATA_WIDTH 16 sync_ram_sdp
+hierarchy -top sync_ram_sdp
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:SB_RAM40_4K
## With parameters
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+hierarchy -top sync_ram_sdp
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:SB_RAM40_4K # too inefficient
select -assert-min 1 t:SB_DFFE
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "block_ram" m:memory
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:SB_RAM40_4K
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "Block_RAM" m:memory
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:SB_RAM40_4K # any case works
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set ram_block 1 m:memory
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 1 t:SB_RAM40_4K
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "registers" m:memory
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:SB_RAM40_4K # requested FFRAM explicitly
select -assert-min 1 t:SB_DFFE
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set logic_block 1 m:memory
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
select -assert-count 0 t:SB_RAM40_4K # requested FFRAM explicitly
select -assert-min 1 t:SB_DFFE
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_romstyle "ebr" m:memory
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
-select -assert-count 1 t:$mem # requested BROM but this is a RAM
+select -assert-count 1 t:$mem_v2 # requested BROM but this is a RAM
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set rom_block 1 m:memory
synth_ice40 -top sync_ram_sdp; cd sync_ram_sdp
-select -assert-count 1 t:$mem # requested BROM but this is a RAM
+select -assert-count 1 t:$mem_v2 # requested BROM but this is a RAM
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set syn_ramstyle "block_ram" m:memory
synth_ice40 -top sync_ram_sdp -nobram; cd sync_ram_sdp
-select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
+select -assert-count 1 t:$mem_v2 # requested BRAM but BRAM is disabled
-design -reset; read_verilog ../common/blockram.v
+design -reset; read_verilog -defer ../common/blockram.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_ram_sdp
+hierarchy -top sync_ram_sdp
setattr -set ram_block 1 m:memory
synth_ice40 -top sync_ram_sdp -nobram; cd sync_ram_sdp
-select -assert-count 1 t:$mem # requested BRAM but BRAM is disabled
+select -assert-count 1 t:$mem_v2 # requested BRAM but BRAM is disabled
# ================================ ROM ================================
# ROM bits <= 4K; Data width <= 16; Address width <= 11: -> SB_RAM40_4K
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 11 -set DATA_WIDTH 2 sync_rom
+hierarchy -top sync_rom
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 1 t:SB_RAM40_4K
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 4 sync_rom
+hierarchy -top sync_rom
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 1 t:SB_RAM40_4K
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 9 -set DATA_WIDTH 8 sync_rom
+hierarchy -top sync_rom
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 1 t:SB_RAM40_4K
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 8 -set DATA_WIDTH 16 sync_rom
+hierarchy -top sync_rom
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 1 t:SB_RAM40_4K
## With parameters
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+hierarchy -top sync_rom
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 0 t:SB_RAM40_4K # too inefficient
select -assert-min 1 t:SB_LUT4
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+hierarchy -top sync_rom
setattr -set syn_romstyle "ebr" m:memory
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 1 t:SB_RAM40_4K
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+hierarchy -top sync_rom
setattr -set rom_block 1 m:memory
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 1 t:SB_RAM40_4K
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+hierarchy -top sync_rom
setattr -set syn_romstyle "logic" m:memory
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 0 t:SB_RAM40_4K # requested LUTROM explicitly
select -assert-min 1 t:SB_LUT4
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+hierarchy -top sync_rom
setattr -set logic_block 1 m:memory
synth_ice40 -top sync_rom; cd sync_rom
select -assert-count 0 t:SB_RAM40_4K # requested LUTROM explicitly
select -assert-min 1 t:SB_LUT4
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+hierarchy -top sync_rom
setattr -set syn_ramstyle "block_ram" m:memory
synth_ice40 -top sync_rom; cd sync_rom
-select -assert-count 1 t:$mem # requested BRAM but this is a ROM
+select -assert-count 1 t:$mem_v2 # requested BRAM but this is a ROM
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+hierarchy -top sync_rom
setattr -set ram_block 1 m:memory
synth_ice40 -top sync_rom; cd sync_rom
-select -assert-count 1 t:$mem # requested BRAM but this is a ROM
+select -assert-count 1 t:$mem_v2 # requested BRAM but this is a ROM
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+hierarchy -top sync_rom
setattr -set syn_romstyle "ebr" m:memory
synth_ice40 -top sync_rom -nobram; cd sync_rom
-select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
+select -assert-count 1 t:$mem_v2 # requested BROM but BRAM is disabled
-design -reset; read_verilog ../common/blockrom.v
+design -reset; read_verilog -defer ../common/blockrom.v
chparam -set ADDRESS_WIDTH 2 -set DATA_WIDTH 8 sync_rom
+hierarchy -top sync_rom
setattr -set rom_block 1 m:memory
synth_ice40 -top sync_rom -nobram; cd sync_rom
-select -assert-count 1 t:$mem # requested BROM but BRAM is disabled
+select -assert-count 1 t:$mem_v2 # requested BROM but BRAM is disabled
diff --git a/tests/arch/intel_alm/add_sub.ys b/tests/arch/intel_alm/add_sub.ys
index 0f552a27c..8f87adf27 100644
--- a/tests/arch/intel_alm/add_sub.ys
+++ b/tests/arch/intel_alm/add_sub.ys
@@ -1,18 +1,18 @@
read_verilog ../common/add_sub.v
hierarchy -top top
-equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
stat
-select -assert-count 8 t:MISTRAL_ALUT_ARITH
+select -assert-count 9 t:MISTRAL_ALUT_ARITH
select -assert-none t:MISTRAL_ALUT_ARITH %% t:* %D
design -reset
read_verilog ../common/add_sub.v
hierarchy -top top
-equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
stat
-select -assert-count 8 t:MISTRAL_ALUT_ARITH
+select -assert-count 9 t:MISTRAL_ALUT_ARITH
select -assert-none t:MISTRAL_ALUT_ARITH %% t:* %D
diff --git a/tests/arch/intel_alm/adffs.ys b/tests/arch/intel_alm/adffs.ys
index 4565dcc64..d7487c40b 100644
--- a/tests/arch/intel_alm/adffs.ys
+++ b/tests/arch/intel_alm/adffs.ys
@@ -3,7 +3,7 @@ design -save read
hierarchy -top adff
proc
-equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd adff # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_FF
@@ -15,7 +15,7 @@ select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D
design -load read
hierarchy -top adff
proc
-equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd adff # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_FF
@@ -27,7 +27,7 @@ select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D
design -load read
hierarchy -top adffn
proc
-equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd adffn # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_FF
@@ -38,7 +38,7 @@ select -assert-none t:MISTRAL_FF %% t:* %D
design -load read
hierarchy -top adffn
proc
-equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd adffn # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_FF
@@ -49,7 +49,7 @@ select -assert-none t:MISTRAL_FF %% t:* %D
design -load read
hierarchy -top dffs
proc
-equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dffs # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_FF
@@ -61,7 +61,7 @@ select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT2 %% t:* %D
design -load read
hierarchy -top dffs
proc
-equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dffs # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_FF
@@ -73,7 +73,7 @@ select -assert-none t:MISTRAL_FF t:MISTRAL_ALUT2 %% t:* %D
design -load read
hierarchy -top ndffnr
proc
-equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd ndffnr # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_FF
@@ -85,7 +85,7 @@ select -assert-none t:MISTRAL_FF t:MISTRAL_NOT %% t:* %D
design -load read
hierarchy -top ndffnr
proc
-equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd ndffnr # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_FF
diff --git a/tests/arch/intel_alm/blockram.ys b/tests/arch/intel_alm/blockram.ys
index 610ae1ffd..c157c3165 100644
--- a/tests/arch/intel_alm/blockram.ys
+++ b/tests/arch/intel_alm/blockram.ys
@@ -1,6 +1,6 @@
read_verilog ../common/blockram.v
chparam -set ADDRESS_WIDTH 10 -set DATA_WIDTH 10 sync_ram_sdp
-synth_intel_alm -family cyclonev
+synth_intel_alm -family cyclonev -noiopad -noclkbuf
cd sync_ram_sdp
select -assert-count 1 t:MISTRAL_M10K
select -assert-none t:MISTRAL_M10K %% t:* %D
diff --git a/tests/arch/intel_alm/counter.ys b/tests/arch/intel_alm/counter.ys
index 50103fefc..56c9cabb3 100644
--- a/tests/arch/intel_alm/counter.ys
+++ b/tests/arch/intel_alm/counter.ys
@@ -2,11 +2,11 @@ read_verilog ../common/counter.v
hierarchy -top top
proc
flatten
-equiv_opt -async2sync -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -async2sync -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
-select -assert-count 2 t:MISTRAL_NOT
+select -assert-count 1 t:MISTRAL_NOT
select -assert-count 8 t:MISTRAL_ALUT_ARITH
select -assert-count 8 t:MISTRAL_FF
select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT_ARITH t:MISTRAL_FF %% t:* %D
@@ -17,11 +17,11 @@ read_verilog ../common/counter.v
hierarchy -top top
proc
flatten
-equiv_opt -async2sync -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -async2sync -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
-select -assert-count 2 t:MISTRAL_NOT
+select -assert-count 1 t:MISTRAL_NOT
select -assert-count 8 t:MISTRAL_ALUT_ARITH
select -assert-count 8 t:MISTRAL_FF
select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT_ARITH t:MISTRAL_FF %% t:* %D
diff --git a/tests/arch/intel_alm/dffs.ys b/tests/arch/intel_alm/dffs.ys
index 9ae6c637a..34b99f04c 100644
--- a/tests/arch/intel_alm/dffs.ys
+++ b/tests/arch/intel_alm/dffs.ys
@@ -3,7 +3,7 @@ design -save read
hierarchy -top dff
proc
-equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dff # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_FF
@@ -13,7 +13,7 @@ select -assert-none t:MISTRAL_FF %% t:* %D
design -load read
hierarchy -top dff
proc
-equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dff # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_FF
@@ -24,7 +24,7 @@ select -assert-none t:MISTRAL_FF %% t:* %D
design -load read
hierarchy -top dffe
proc
-equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dffe # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_FF
@@ -35,7 +35,7 @@ select -assert-none t:MISTRAL_FF %% t:* %D
design -load read
hierarchy -top dffe
proc
-equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd dffe # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_FF
diff --git a/tests/arch/intel_alm/fsm.ys b/tests/arch/intel_alm/fsm.ys
index e54b5c21e..0aeea450a 100644
--- a/tests/arch/intel_alm/fsm.ys
+++ b/tests/arch/intel_alm/fsm.ys
@@ -3,7 +3,7 @@ hierarchy -top fsm
proc
flatten
-equiv_opt -run :prove -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev
+equiv_opt -run :prove -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf
async2sync
miter -equiv -make_assert -flatten gold gate miter
sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter
@@ -26,7 +26,7 @@ hierarchy -top fsm
proc
flatten
-equiv_opt -run :prove -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx
+equiv_opt -run :prove -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf
async2sync
miter -equiv -make_assert -flatten gold gate miter
sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter
diff --git a/tests/arch/intel_alm/logic.ys b/tests/arch/intel_alm/logic.ys
index e8b26a524..d34d1bc65 100644
--- a/tests/arch/intel_alm/logic.ys
+++ b/tests/arch/intel_alm/logic.ys
@@ -1,7 +1,7 @@
read_verilog ../common/logic.v
hierarchy -top top
proc
-equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
@@ -15,7 +15,7 @@ design -reset
read_verilog ../common/logic.v
hierarchy -top top
proc
-equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
diff --git a/tests/arch/intel_alm/lutram.ys b/tests/arch/intel_alm/lutram.ys
index 66f8a1536..9ddb1ec87 100644
--- a/tests/arch/intel_alm/lutram.ys
+++ b/tests/arch/intel_alm/lutram.ys
@@ -2,7 +2,7 @@ read_verilog ../common/lutram.v
hierarchy -top lutram_1w1r
proc
memory -nomap
-equiv_opt -run :prove -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v -map +/intel_alm/common/mem_sim.v synth_intel_alm -family cyclonev -nobram
+equiv_opt -run :prove -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v -map +/intel_alm/common/mem_sim.v synth_intel_alm -family cyclonev -nobram -noiopad -noclkbuf
memory
opt -full
@@ -12,11 +12,10 @@ sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs mite
design -load postopt
cd lutram_1w1r
select -assert-count 16 t:MISTRAL_MLAB
-select -assert-count 1 t:MISTRAL_NOT
select -assert-count 2 t:MISTRAL_ALUT2
select -assert-count 8 t:MISTRAL_ALUT3
-select -assert-count 17 t:MISTRAL_FF
-select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_FF t:MISTRAL_MLAB %% t:* %D
+select -assert-count 8 t:MISTRAL_FF
+select -assert-none t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_FF t:MISTRAL_MLAB %% t:* %D
design -reset
@@ -24,7 +23,7 @@ read_verilog ../common/lutram.v
hierarchy -top lutram_1w1r
proc
memory -nomap
-equiv_opt -run :prove -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v -map +/intel_alm/common/mem_sim.v synth_intel_alm -family cyclonev -nobram
+equiv_opt -run :prove -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v -map +/intel_alm/common/mem_sim.v synth_intel_alm -family cyclonev -nobram -noiopad -noclkbuf
memory
opt -full
@@ -34,8 +33,7 @@ sat -verify -prove-asserts -seq 3 -set-init-zero -show-inputs -show-outputs mite
design -load postopt
cd lutram_1w1r
select -assert-count 16 t:MISTRAL_MLAB
-select -assert-count 1 t:MISTRAL_NOT
select -assert-count 2 t:MISTRAL_ALUT2
select -assert-count 8 t:MISTRAL_ALUT3
-select -assert-count 17 t:MISTRAL_FF
-select -assert-none t:MISTRAL_NOT t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_FF t:MISTRAL_MLAB %% t:* %D
+select -assert-count 8 t:MISTRAL_FF
+select -assert-none t:MISTRAL_ALUT2 t:MISTRAL_ALUT3 t:MISTRAL_FF t:MISTRAL_MLAB %% t:* %D
diff --git a/tests/arch/intel_alm/mul.ys b/tests/arch/intel_alm/mul.ys
index 49934740f..e147d93ac 100644
--- a/tests/arch/intel_alm/mul.ys
+++ b/tests/arch/intel_alm/mul.ys
@@ -2,7 +2,7 @@ read_verilog ../common/mul.v
chparam -set X_WIDTH 8 -set Y_WIDTH 8 -set A_WIDTH 16
hierarchy -top top
proc
-equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
@@ -16,7 +16,7 @@ read_verilog ../common/mul.v
chparam -set X_WIDTH 17 -set Y_WIDTH 17 -set A_WIDTH 34
hierarchy -top top
proc
-equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
@@ -28,7 +28,7 @@ read_verilog ../common/mul.v
chparam -set X_WIDTH 17 -set Y_WIDTH 17 -set A_WIDTH 34
hierarchy -top top
proc
-equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
@@ -40,7 +40,7 @@ read_verilog ../common/mul.v
chparam -set X_WIDTH 26 -set Y_WIDTH 26 -set A_WIDTH 52
hierarchy -top top
proc
-equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
@@ -52,7 +52,7 @@ read_verilog ../common/mul.v
chparam -set X_WIDTH 26 -set Y_WIDTH 26 -set A_WIDTH 52
hierarchy -top top
proc
-equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
diff --git a/tests/arch/intel_alm/mux.ys b/tests/arch/intel_alm/mux.ys
index ac3b9b08f..6fb6ae80a 100644
--- a/tests/arch/intel_alm/mux.ys
+++ b/tests/arch/intel_alm/mux.ys
@@ -4,7 +4,7 @@ design -save read
hierarchy -top mux2
proc
-equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux2 # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_ALUT3
@@ -14,7 +14,7 @@ select -assert-none t:MISTRAL_ALUT3 %% t:* %D
design -load read
hierarchy -top mux2
proc
-equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux2 # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_ALUT3
@@ -24,7 +24,7 @@ select -assert-none t:MISTRAL_ALUT3 %% t:* %D
design -load read
hierarchy -top mux4
proc
-equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux4 # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_ALUT6
@@ -34,7 +34,7 @@ select -assert-none t:MISTRAL_ALUT6 %% t:* %D
design -load read
hierarchy -top mux4
proc
-equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux4 # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_ALUT6
@@ -44,7 +44,7 @@ select -assert-none t:MISTRAL_ALUT6 %% t:* %D
design -load read
hierarchy -top mux8
proc
-equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux8 # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_ALUT3
@@ -55,7 +55,7 @@ select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT6 %% t:* %D
design -load read
hierarchy -top mux8
proc
-equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux8 # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_ALUT3
@@ -66,7 +66,7 @@ select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT6 %% t:* %D
design -load read
hierarchy -top mux16
proc
-equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux16 # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_ALUT3
@@ -78,7 +78,7 @@ select -assert-none t:MISTRAL_ALUT3 t:MISTRAL_ALUT5 t:MISTRAL_ALUT6 %% t:* %D
design -load read
hierarchy -top mux16
proc
-equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -assert -map +/intel_alm/common/alm_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux16 # Constrain all select calls below inside the top module
select -assert-count 1 t:MISTRAL_ALUT3
diff --git a/tests/arch/intel_alm/quartus_ice.ys b/tests/arch/intel_alm/quartus_ice.ys
index a88226e13..4e1896b82 100644
--- a/tests/arch/intel_alm/quartus_ice.ys
+++ b/tests/arch/intel_alm/quartus_ice.ys
@@ -22,5 +22,5 @@ module top();
endmodule
EOT
-synth_intel_alm -family cyclone10gx -quartus
+synth_intel_alm -family cyclone10gx -quartus -noiopad -noclkbuf
select -assert-none w:*[* w:*]*
diff --git a/tests/arch/intel_alm/shifter.ys b/tests/arch/intel_alm/shifter.ys
index e307b5486..77ff98896 100644
--- a/tests/arch/intel_alm/shifter.ys
+++ b/tests/arch/intel_alm/shifter.ys
@@ -2,7 +2,7 @@ read_verilog ../common/shifter.v
hierarchy -top top
proc
flatten
-equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
select -assert-count 8 t:MISTRAL_FF
@@ -14,7 +14,7 @@ read_verilog ../common/shifter.v
hierarchy -top top
proc
flatten
-equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -async2sync -assert -map +/intel_alm/common/alm_sim.v -map +/intel_alm/common/dff_sim.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd top # Constrain all select calls below inside the top module
select -assert-count 8 t:MISTRAL_FF
diff --git a/tests/arch/intel_alm/tribuf.ys b/tests/arch/intel_alm/tribuf.ys
index 7f3b38493..fb5fecb78 100644
--- a/tests/arch/intel_alm/tribuf.ys
+++ b/tests/arch/intel_alm/tribuf.ys
@@ -4,7 +4,7 @@ proc
tribuf
flatten
synth
-equiv_opt -assert -map +/simcells.v synth_intel_alm -family cyclonev # equivalency check
+equiv_opt -assert -map +/simcells.v synth_intel_alm -family cyclonev -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd tristate # Constrain all select calls below inside the top module
#Internal cell type used. Need support it.
@@ -19,7 +19,7 @@ proc
tribuf
flatten
synth
-equiv_opt -assert -map +/simcells.v synth_intel_alm -family cyclone10gx # equivalency check
+equiv_opt -assert -map +/simcells.v synth_intel_alm -family cyclone10gx -noiopad -noclkbuf # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd tristate # Constrain all select calls below inside the top module
#Internal cell type used. Need support it.
diff --git a/tests/arch/machxo2/mux.ys b/tests/arch/machxo2/mux.ys
index 6c8aa857c..7b7e62d4c 100644
--- a/tests/arch/machxo2/mux.ys
+++ b/tests/arch/machxo2/mux.ys
@@ -35,6 +35,6 @@ proc
equiv_opt -assert -map +/machxo2/cells_sim.v synth_machxo2 # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd mux16 # Constrain all select calls below inside the top module
-select -assert-count 11 t:LUT4
+select -assert-max 12 t:LUT4
select -assert-none t:LUT4 t:FACADE_IO %% t:* %D
diff --git a/tests/arch/machxo2/tribuf.ys b/tests/arch/machxo2/tribuf.ys
index 9c00a8bcf..fce342e18 100644
--- a/tests/arch/machxo2/tribuf.ys
+++ b/tests/arch/machxo2/tribuf.ys
@@ -6,5 +6,5 @@ equiv_opt -assert -map +/machxo2/cells_sim.v synth_machxo2 # equivalency check
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
cd tristate # Constrain all select calls below inside the top module
select -assert-count 3 t:FACADE_IO
-select -assert-count 1 t:$not
-select -assert-none t:FACADE_IO t:$not %% t:* %D
+select -assert-count 1 t:LUT4
+select -assert-none t:FACADE_IO t:LUT4 %% t:* %D
diff --git a/tests/arch/nexus/lutram.ys b/tests/arch/nexus/lutram.ys
index cd645f717..6e33431b6 100644
--- a/tests/arch/nexus/lutram.ys
+++ b/tests/arch/nexus/lutram.ys
@@ -13,7 +13,7 @@ design -load postopt
cd lutram_1w1r
stat
select -assert-count 8 t:WIDEFN9
-select -assert-count 16 t:LUT4
+select -assert-count 12 t:LUT4
select -assert-count 8 t:DPR16X4
-select -assert-count 36 t:FD1P3IX
+select -assert-count 8 t:FD1P3IX
select -assert-none t:DPR16X4 t:FD1P3IX t:WIDEFN9 t:LUT4 t:INV t:IB t:OB t:VLO t:VHI %% t:* %D
diff --git a/tests/arch/quicklogic/.gitignore b/tests/arch/quicklogic/.gitignore
new file mode 100644
index 000000000..9a71dca69
--- /dev/null
+++ b/tests/arch/quicklogic/.gitignore
@@ -0,0 +1,4 @@
+*.log
+/run-test.mk
++*_synth.v
++*_testbench
diff --git a/tests/arch/quicklogic/add_sub.ys b/tests/arch/quicklogic/add_sub.ys
new file mode 100644
index 000000000..73ee5cb44
--- /dev/null
+++ b/tests/arch/quicklogic/add_sub.ys
@@ -0,0 +1,11 @@
+read_verilog ../common/add_sub.v
+hierarchy -top top
+equiv_opt -assert -map +/quicklogic/lut_sim.v -map +/quicklogic/pp3_cells_sim.v synth_quicklogic -family pp3 # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+select -assert-count 2 t:LUT2
+select -assert-count 8 t:LUT3
+select -assert-count 2 t:LUT4
+select -assert-count 8 t:inpad
+select -assert-count 8 t:outpad
+select -assert-none t:LUT2 t:LUT3 t:LUT4 t:inpad t:outpad %% t:* %D
diff --git a/tests/arch/quicklogic/adffs.ys b/tests/arch/quicklogic/adffs.ys
new file mode 100644
index 000000000..41a175844
--- /dev/null
+++ b/tests/arch/quicklogic/adffs.ys
@@ -0,0 +1,67 @@
+read_verilog ../common/adffs.v
+design -save read
+
+hierarchy -top adff
+proc
+equiv_opt -async2sync -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v synth_quicklogic # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd adff # Constrain all select calls below inside the top module
+select -assert-count 1 t:dffepc
+select -assert-count 1 t:logic_0
+select -assert-count 1 t:logic_1
+select -assert-count 1 t:inpad
+select -assert-count 1 t:outpad
+select -assert-count 2 t:ckpad
+
+select -assert-none t:dffepc t:logic_0 t:logic_1 t:inpad t:outpad t:ckpad %% t:* %D
+
+
+design -load read
+hierarchy -top adffn
+proc
+equiv_opt -async2sync -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd adffn # Constrain all select calls below inside the top module
+select -assert-count 1 t:LUT1
+select -assert-count 1 t:dffepc
+select -assert-count 1 t:logic_0
+select -assert-count 1 t:logic_1
+select -assert-count 2 t:inpad
+select -assert-count 1 t:outpad
+select -assert-count 1 t:ckpad
+
+select -assert-none t:LUT1 t:dffepc t:logic_0 t:logic_1 t:inpad t:outpad t:ckpad %% t:* %D
+
+
+design -load read
+hierarchy -top dffs
+proc
+equiv_opt -async2sync -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd dffs # Constrain all select calls below inside the top module
+select -assert-count 1 t:LUT2
+select -assert-count 1 t:dffepc
+select -assert-count 1 t:logic_0
+select -assert-count 1 t:logic_1
+select -assert-count 3 t:inpad
+select -assert-count 1 t:outpad
+select -assert-count 1 t:ckpad
+
+select -assert-none t:LUT2 t:dffepc t:logic_0 t:logic_1 t:inpad t:outpad t:ckpad %% t:* %D
+
+
+design -load read
+hierarchy -top ndffnr
+proc
+equiv_opt -async2sync -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd ndffnr # Constrain all select calls below inside the top module
+select -assert-count 1 t:LUT1
+select -assert-count 1 t:LUT2
+select -assert-count 1 t:dffepc
+select -assert-count 1 t:logic_0
+select -assert-count 1 t:logic_1
+select -assert-count 4 t:inpad
+select -assert-count 1 t:outpad
+
+select -assert-none t:LUT1 t:LUT2 t:dffepc t:logic_0 t:logic_1 t:inpad t:outpad %% t:* %D
diff --git a/tests/arch/quicklogic/counter.ys b/tests/arch/quicklogic/counter.ys
new file mode 100644
index 000000000..2e266417c
--- /dev/null
+++ b/tests/arch/quicklogic/counter.ys
@@ -0,0 +1,18 @@
+read_verilog ../common/counter.v
+hierarchy -top top
+proc
+flatten
+equiv_opt -assert -multiclock -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+select -assert-count 1 t:LUT1
+select -assert-count 3 t:LUT2
+select -assert-count 5 t:LUT3
+select -assert-count 1 t:LUT4
+select -assert-count 8 t:dffepc
+select -assert-count 1 t:logic_0
+select -assert-count 1 t:logic_1
+select -assert-count 8 t:outpad
+select -assert-count 2 t:ckpad
+
+select -assert-none t:LUT1 t:LUT2 t:LUT3 t:LUT4 t:dffepc t:logic_0 t:logic_1 t:outpad t:ckpad %% t:* %D
diff --git a/tests/arch/quicklogic/dffs.ys b/tests/arch/quicklogic/dffs.ys
new file mode 100644
index 000000000..2e0a34540
--- /dev/null
+++ b/tests/arch/quicklogic/dffs.ys
@@ -0,0 +1,20 @@
+read_verilog ../common/dffs.v
+rename dff my_dff # Work around conflicting module names between test and vendor cells
+rename dffe my_dffe
+design -save read
+
+hierarchy -top my_dff
+proc
+equiv_opt -async2sync -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v synth_quicklogic # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd dff # Constrain all select calls below inside the top module
+select -assert-none t:*
+
+design -load read
+hierarchy -top my_dffe
+proc
+equiv_opt -async2sync -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v synth_quicklogic # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd dffe # Constrain all select calls below inside the top module
+
+select -assert-none t:* \ No newline at end of file
diff --git a/tests/arch/quicklogic/fsm.ys b/tests/arch/quicklogic/fsm.ys
new file mode 100644
index 000000000..130dacf42
--- /dev/null
+++ b/tests/arch/quicklogic/fsm.ys
@@ -0,0 +1,23 @@
+read_verilog ../common/fsm.v
+hierarchy -top fsm
+proc
+flatten
+
+equiv_opt -run :prove -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic
+async2sync
+miter -equiv -make_assert -flatten gold gate miter
+sat -verify -prove-asserts -show-public -set-at 1 in_reset 1 -seq 20 -prove-skip 1 miter
+
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd fsm # Constrain all select calls below inside the top module
+
+select -assert-count 1 t:LUT2
+select -assert-count 9 t:LUT3
+select -assert-count 4 t:dffepc
+select -assert-count 1 t:logic_0
+select -assert-count 1 t:logic_1
+select -assert-count 3 t:inpad
+select -assert-count 2 t:outpad
+select -assert-count 1 t:ckpad
+
+select -assert-none t:LUT2 t:LUT3 t:dffepc t:logic_0 t:logic_1 t:inpad t:outpad t:ckpad %% t:* %D
diff --git a/tests/arch/quicklogic/latches.ys b/tests/arch/quicklogic/latches.ys
new file mode 100644
index 000000000..bcef42990
--- /dev/null
+++ b/tests/arch/quicklogic/latches.ys
@@ -0,0 +1,40 @@
+read_verilog ../common/latches.v
+design -save read
+
+hierarchy -top latchp
+proc
+# Can't run any sort of equivalence check because latches are blown to LUTs
+synth_quicklogic
+cd latchp # Constrain all select calls below inside the top module
+select -assert-count 1 t:LUT3
+select -assert-count 3 t:inpad
+select -assert-count 1 t:outpad
+
+select -assert-none t:LUT3 t:inpad t:outpad %% t:* %D
+
+
+design -load read
+hierarchy -top latchn
+proc
+# Can't run any sort of equivalence check because latches are blown to LUTs
+synth_quicklogic
+cd latchn # Constrain all select calls below inside the top module
+select -assert-count 1 t:LUT3
+select -assert-count 3 t:inpad
+select -assert-count 1 t:outpad
+
+select -assert-none t:LUT3 t:inpad t:outpad %% t:* %D
+
+
+design -load read
+hierarchy -top latchsr
+proc
+# Can't run any sort of equivalence check because latches are blown to LUTs
+synth_quicklogic
+cd latchsr # Constrain all select calls below inside the top module
+select -assert-count 1 t:LUT2
+select -assert-count 1 t:LUT4
+select -assert-count 5 t:inpad
+select -assert-count 1 t:outpad
+
+select -assert-none t:LUT2 t:LUT4 t:inpad t:outpad %% t:* %D
diff --git a/tests/arch/quicklogic/logic.ys b/tests/arch/quicklogic/logic.ys
new file mode 100644
index 000000000..4b327c00a
--- /dev/null
+++ b/tests/arch/quicklogic/logic.ys
@@ -0,0 +1,14 @@
+read_verilog ../common/logic.v
+hierarchy -top top
+proc
+equiv_opt -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd top # Constrain all select calls below inside the top module
+
+select -assert-count 1 t:LUT1
+select -assert-count 6 t:LUT2
+select -assert-count 2 t:LUT3
+select -assert-count 8 t:inpad
+select -assert-count 10 t:outpad
+
+select -assert-none t:LUT1 t:LUT2 t:LUT3 t:inpad t:outpad %% t:* %D
diff --git a/tests/arch/quicklogic/mux.ys b/tests/arch/quicklogic/mux.ys
new file mode 100644
index 000000000..ea17fa99b
--- /dev/null
+++ b/tests/arch/quicklogic/mux.ys
@@ -0,0 +1,52 @@
+read_verilog ../common/mux.v
+design -save read
+
+hierarchy -top mux2
+proc
+equiv_opt -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mux2 # Constrain all select calls below inside the top module
+select -assert-count 1 t:LUT3
+select -assert-count 3 t:inpad
+select -assert-count 1 t:outpad
+
+select -assert-none t:LUT3 t:inpad t:outpad %% t:* %D
+
+design -load read
+hierarchy -top mux4
+proc
+equiv_opt -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mux4 # Constrain all select calls below inside the top module
+select -assert-count 3 t:LUT3
+select -assert-count 6 t:inpad
+select -assert-count 1 t:outpad
+
+select -assert-none t:LUT3 t:inpad t:outpad %% t:* %D
+
+design -load read
+hierarchy -top mux8
+proc
+equiv_opt -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mux8 # Constrain all select calls below inside the top module
+select -assert-count 1 t:LUT1
+select -assert-count 1 t:LUT3
+select -assert-count 2 t:mux4x0
+select -assert-count 11 t:inpad
+select -assert-count 1 t:outpad
+
+select -assert-none t:LUT1 t:LUT3 t:mux4x0 t:inpad t:outpad %% t:* %D
+
+design -load read
+hierarchy -top mux16
+proc
+equiv_opt -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/quicklogic/lut_sim.v synth_quicklogic # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd mux16 # Constrain all select calls below inside the top module
+select -assert-count 1 t:LUT3
+select -assert-count 2 t:mux8x0
+select -assert-count 20 t:inpad
+select -assert-count 1 t:outpad
+
+select -assert-none t:LUT3 t:mux8x0 t:inpad t:outpad %% t:* %D
diff --git a/tests/arch/quicklogic/run-test.sh b/tests/arch/quicklogic/run-test.sh
new file mode 100755
index 000000000..4be4b70ae
--- /dev/null
+++ b/tests/arch/quicklogic/run-test.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+set -eu
+source ../../gen-tests-makefile.sh
+run_tests --yosys-scripts --bash --yosys-args "-w 'Yosys has only limited support for tri-state logic at the moment.'"
diff --git a/tests/arch/quicklogic/tribuf.ys b/tests/arch/quicklogic/tribuf.ys
new file mode 100644
index 000000000..de763009e
--- /dev/null
+++ b/tests/arch/quicklogic/tribuf.ys
@@ -0,0 +1,13 @@
+read_verilog ../common/tribuf.v
+hierarchy -top tristate
+proc
+tribuf
+flatten
+synth
+equiv_opt -assert -map +/quicklogic/pp3_cells_sim.v -map +/quicklogic/cells_sim.v -map +/simcells.v synth_quicklogic # equivalency check
+design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
+cd tristate # Constrain all select calls below inside the top module
+select -assert-count 2 t:inpad
+select -assert-count 1 t:outpad
+select -assert-count 1 t:$_TBUF_
+select -assert-none t:inpad t:outpad t:$_TBUF_ %% t:* %D
diff --git a/tests/arch/run-test.sh b/tests/arch/run-test.sh
index 170078a7f..5d923db56 100755
--- a/tests/arch/run-test.sh
+++ b/tests/arch/run-test.sh
@@ -11,7 +11,7 @@ for arch in ../../techlibs/*; do
if [ "${defines[$arch_name]}" ]; then
for def in ${defines[$arch_name]}; do
echo -n "Test $path -D$def ->"
- iverilog -t null -I$arch -D$def $path
+ iverilog -t null -I$arch -D$def -DNO_ICE40_DEFAULT_ASSIGNMENTS $path
echo " ok"
done
else
diff --git a/tests/arch/xilinx/abc9_dff.ys b/tests/arch/xilinx/abc9_dff.ys
index 210e87477..0ba3901f7 100644
--- a/tests/arch/xilinx/abc9_dff.ys
+++ b/tests/arch/xilinx/abc9_dff.ys
@@ -50,10 +50,10 @@ FDCE_1 /*#(.INIT(1))*/ fd7(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[6]));
FDPE_1 #(.INIT(1)) fd8(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[7]));
endmodule
EOT
-logger -expect warning "Whitebox '\$paramod\\FDRE\\INIT=1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1
-logger -expect warning "Whitebox '\$paramod\\FDRE_1\\INIT=1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1
+logger -expect warning "Whitebox '\$paramod\\FDRE\\INIT=.*1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1
+logger -expect warning "Whitebox '\$paramod\\FDRE_1\\INIT=.*1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1
logger -expect warning "Whitebox 'FDSE' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1
-logger -expect warning "Whitebox '\$paramod\\FDSE_1\\INIT=1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1
+logger -expect warning "Whitebox '\$paramod\\FDSE_1\\INIT=.*1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1
equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf
design -load postopt
select -assert-count 8 t:FD*
diff --git a/tests/arch/xilinx/fsm.ys b/tests/arch/xilinx/fsm.ys
index ace646af4..3b1919627 100644
--- a/tests/arch/xilinx/fsm.ys
+++ b/tests/arch/xilinx/fsm.ys
@@ -31,6 +31,7 @@ stat
select -assert-count 1 t:BUFG
select -assert-count 6 t:FDRE
select -assert-count 1 t:LUT1
-select -assert-count 8 t:LUT4
+select -assert-max 1 t:LUT3
+select -assert-max 8 t:LUT4
select -assert-count 5 t:MUXF5
-select -assert-none t:BUFG t:FDRE t:LUT1 t:LUT4 t:MUXF5 %% t:* %D
+select -assert-none t:BUFG t:FDRE t:LUT1 t:LUT3 t:LUT4 t:MUXF5 %% t:* %D
diff --git a/tests/arch/xilinx/tribuf.sh b/tests/arch/xilinx/tribuf.sh
index bd44395cb..eca33e490 100644
--- a/tests/arch/xilinx/tribuf.sh
+++ b/tests/arch/xilinx/tribuf.sh
@@ -1,5 +1,5 @@
-! ../../../yosys -qp "synth_xilinx" ../common/tribuf.v
-../../../yosys -qp "synth_xilinx -iopad; \
+../../../yosys -f verilog -qp "synth_xilinx" ../common/tribuf.v
+../../../yosys -f verilog -qp "synth_xilinx -iopad; \
select -assert-count 2 t:IBUF; \
select -assert-count 1 t:INV; \
select -assert-count 1 t:OBUFT" ../common/tribuf.v
diff --git a/tests/bind/.gitignore b/tests/bind/.gitignore
new file mode 100644
index 000000000..8355de9dc
--- /dev/null
+++ b/tests/bind/.gitignore
@@ -0,0 +1,2 @@
+*.log
+run-test.mk
diff --git a/tests/bind/basic.sv b/tests/bind/basic.sv
new file mode 100644
index 000000000..ce0d04c48
--- /dev/null
+++ b/tests/bind/basic.sv
@@ -0,0 +1,20 @@
+// A basic example of the bind construct
+
+module foo (input logic a, input logic b, output logic c);
+ // Magic happens here...
+endmodule
+
+module bar (input a, input b, output c);
+ assign c = a ^ b;
+endmodule
+
+module top ();
+ logic u, v, w;
+ foo foo_i (.a (u), .b (v), .c (w));
+
+ bind foo bar bound_i (.*);
+
+ always_comb begin
+ assert(w == u ^ v);
+ end
+endmodule
diff --git a/tests/bind/basic.ys b/tests/bind/basic.ys
new file mode 100644
index 000000000..266fa4e48
--- /dev/null
+++ b/tests/bind/basic.ys
@@ -0,0 +1 @@
+read_verilog -sv basic.sv
diff --git a/tests/bind/cell_list.sv b/tests/bind/cell_list.sv
new file mode 100644
index 000000000..c0da13d29
--- /dev/null
+++ b/tests/bind/cell_list.sv
@@ -0,0 +1,26 @@
+// An example of specifying multiple bind instances in a single directive. This
+// also uses explicit bound names.
+
+module foo (input logic a0, input logic b0, output logic c0,
+ input logic a1, input logic b1, output logic c1);
+ // Magic happens here...
+endmodule
+
+module bar (input a, input b, output c);
+ assign c = a ^ b;
+endmodule
+
+module top ();
+ logic u0, v0, w0;
+ logic u1, v1, w1;
+
+ foo foo0 (.a0 (u0), .b0 (v0), .c0 (w0),
+ .a1 (u1), .b1 (v1), .c1 (w1));
+
+ bind foo bar bar0 (.a(a0), .b(b0), .c(c0)), bar1 (.a(a1), .b(b1), .c(c1));
+
+ always_comb begin
+ assert(w0 == u0 ^ v0);
+ assert(w1 == u1 ^ v1);
+ end
+endmodule
diff --git a/tests/bind/cell_list.ys b/tests/bind/cell_list.ys
new file mode 100644
index 000000000..9afd9a941
--- /dev/null
+++ b/tests/bind/cell_list.ys
@@ -0,0 +1 @@
+read_verilog -sv cell_list.sv
diff --git a/tests/bind/hier.sv b/tests/bind/hier.sv
new file mode 100644
index 000000000..fd3bc62b8
--- /dev/null
+++ b/tests/bind/hier.sv
@@ -0,0 +1,20 @@
+// An example of the bind construct using a hierarchical reference starting with $root
+
+module foo (input logic a, input logic b, output logic c);
+ // Magic happens here...
+endmodule
+
+module bar (input a, input b, output c);
+ assign c = a ^ b;
+endmodule
+
+module top ();
+ logic u, v, w;
+ foo foo_i (.a (u), .b (v), .c (w));
+
+ always_comb begin
+ assert(w == u ^ v);
+ end
+endmodule
+
+bind $root.top.foo_i bar bound_i (.*);
diff --git a/tests/bind/hier.ys b/tests/bind/hier.ys
new file mode 100644
index 000000000..c19fba100
--- /dev/null
+++ b/tests/bind/hier.ys
@@ -0,0 +1 @@
+read_verilog -sv hier.sv
diff --git a/tests/bind/inst_list.sv b/tests/bind/inst_list.sv
new file mode 100644
index 000000000..e0077caec
--- /dev/null
+++ b/tests/bind/inst_list.sv
@@ -0,0 +1,24 @@
+// An example of specifying multiple bind targets with an instance list
+
+module foo (input logic a, input logic b, output logic c);
+ // Magic happens here...
+endmodule
+
+module bar (input a, input b, output c);
+ assign c = a ^ b;
+endmodule
+
+module top ();
+ logic u0, v0, w0;
+ logic u1, v1, w1;
+
+ foo foo0 (.a (u0), .b (v0), .c (w0));
+ foo foo1 (.a (u1), .b (v1), .c (w1));
+
+ bind foo : foo0, foo1 bar bound_i (.*);
+
+ always_comb begin
+ assert(w0 == u0 ^ v0);
+ assert(w1 == u1 ^ v1);
+ end
+endmodule
diff --git a/tests/bind/inst_list.ys b/tests/bind/inst_list.ys
new file mode 100644
index 000000000..ac1385b83
--- /dev/null
+++ b/tests/bind/inst_list.ys
@@ -0,0 +1 @@
+read_verilog -sv inst_list.sv
diff --git a/tests/bind/param.sv b/tests/bind/param.sv
new file mode 100644
index 000000000..c7793527a
--- /dev/null
+++ b/tests/bind/param.sv
@@ -0,0 +1,26 @@
+// An example showing how parameters get inferred when binding
+
+module foo (input logic a, input logic b, output logic c);
+ parameter doit = 1;
+
+ // Magic happens here...
+endmodule
+
+module bar (input a, input b, output c);
+ parameter doit = 1;
+
+ assign c = doit ? a ^ b : 0;
+endmodule
+
+module top (input u0, input v0, output w0,
+ input u1, input v1, output w1);
+ foo #(.doit (0)) foo0 (.a (u0), .b (v0), .c (w0));
+ foo #(.doit (1)) foo1 (.a (u1), .b (v1), .c (w1));
+
+ bind foo bar #(.doit (doit)) bound_i (.*);
+
+ always_comb begin
+ assert (w0 == '0);
+ assert (w1 == u1 ^ v1);
+ end
+endmodule
diff --git a/tests/bind/param.ys b/tests/bind/param.ys
new file mode 100644
index 000000000..a43d05759
--- /dev/null
+++ b/tests/bind/param.ys
@@ -0,0 +1 @@
+read_verilog -sv param.sv
diff --git a/tests/bind/run-test.sh b/tests/bind/run-test.sh
new file mode 100755
index 000000000..ea56b70f0
--- /dev/null
+++ b/tests/bind/run-test.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+set -e
+{
+echo "all::"
+for x in *.ys; do
+ echo "all:: run-$x"
+ echo "run-$x:"
+ echo " @echo 'Running $x..'"
+ echo " @../../yosys -ql ${x%.ys}.log $x"
+done
+for s in *.sh; do
+ if [ "$s" != "run-test.sh" ]; then
+ echo "all:: run-$s"
+ echo "run-$s:"
+ echo " @echo 'Running $s..'"
+ echo " @bash $s"
+ fi
+done
+} > run-test.mk
+exec ${MAKE:-make} -f run-test.mk
diff --git a/tests/bind/toplevel.sv b/tests/bind/toplevel.sv
new file mode 100644
index 000000000..328edcf67
--- /dev/null
+++ b/tests/bind/toplevel.sv
@@ -0,0 +1,20 @@
+// The bind construct occurring at top-level in the script
+
+module foo (input logic a, input logic b, output logic c);
+ // Magic happens here...
+endmodule
+
+module bar (input a, input b, output c);
+ assign c = a ^ b;
+endmodule
+
+module top ();
+ logic u, v, w;
+ foo foo_i (.a (u), .b (v), .c (w));
+
+ always_comb begin
+ assert(w == u ^ v);
+ end
+endmodule
+
+bind top.foo_i bar bound_i (.*);
diff --git a/tests/bind/toplevel.ys b/tests/bind/toplevel.ys
new file mode 100644
index 000000000..11c0ada19
--- /dev/null
+++ b/tests/bind/toplevel.ys
@@ -0,0 +1 @@
+read_verilog -sv toplevel.sv
diff --git a/tests/blif/.gitignore b/tests/blif/.gitignore
new file mode 100644
index 000000000..397b4a762
--- /dev/null
+++ b/tests/blif/.gitignore
@@ -0,0 +1 @@
+*.log
diff --git a/tests/blif/bug2729.ys b/tests/blif/bug2729.ys
new file mode 100644
index 000000000..0cbc21aa0
--- /dev/null
+++ b/tests/blif/bug2729.ys
@@ -0,0 +1,20 @@
+read_verilog <<EOF
+
+module cell (input [2:12] I, output [5:-5] O);
+endmodule
+
+module top(input [10:0] A, output [10:0] B);
+cell my_cell(.I(A), .O(B));
+endmodule
+
+EOF
+
+write_blif tmp-bug2729.blif
+delete top
+read_blif -wideports tmp-bug2729.blif
+!rm tmp-bug2729.blif
+rename -enumerate t:cell
+dump
+cd top
+connect -assert -port _0_ I A
+connect -assert -port _0_ O B
diff --git a/tests/blif/run-test.sh b/tests/blif/run-test.sh
new file mode 100755
index 000000000..44ce7e674
--- /dev/null
+++ b/tests/blif/run-test.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+set -e
+for x in *.ys; do
+ echo "Running $x.."
+ ../../yosys -ql ${x%.ys}.log $x
+done
diff --git a/tests/bram/generate.py b/tests/bram/generate.py
index def0b23c1..79dd500a3 100644
--- a/tests/bram/generate.py
+++ b/tests/bram/generate.py
@@ -93,18 +93,22 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2, or_next):
tb_dout = list()
tb_addrlist = list()
+ addrmask = (1 << abits) - 1
+
for i in range(10):
- tb_addrlist.append(random.randrange(1048576))
+ tb_addrlist.append(random.randrange(1048576) & addrmask)
t = random.randrange(1048576)
for i in range(10):
- tb_addrlist.append(t ^ (1 << i))
+ tb_addrlist.append((t ^ (1 << i)) & addrmask)
v_stmts.append("(* nomem2reg *) reg [%d:0] memory [0:%d];" % (dbits-1, 2**abits-1))
portindex = 0
last_always_hdr = (-1, "")
+ addr2en = {}
+
for p1 in range(groups):
for p2 in range(ports[p1]):
pf = "%c%d" % (chr(ord("A") + p1), p2 + 1)
@@ -143,6 +147,7 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2, or_next):
v_stmts.append("input [%d:0] %sEN;" % (enable[p1]-1, pf))
tb_decls.append("reg [%d:0] %sEN;" % (enable[p1]-1, pf))
tb_din.append("%sEN" % pf)
+ addr2en["%sADDR" % pf] = "%sEN" % pf
assign_op = "<="
if clocks[p1] == 0:
@@ -247,10 +252,23 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2, or_next):
print(" #100;", file=tb_f)
print(" $display(\"bram_%02d_%02d %3d: %%b %%b %%s\", %s, %s, error ? \"ERROR\" : \"OK\");" %
(k1, k2, i, expr_dout, expr_dout_ref), file=tb_f)
- for p in tb_din:
- print(" %s <= %d;" % (p, random.randrange(1048576)), file=tb_f)
+ a2e = {}
for p in tb_addr:
- print(" %s <= %d;" % (p, random.choice(tb_addrlist)), file=tb_f)
+ addr = random.choice(tb_addrlist)
+ if p in addr2en:
+ if addr not in a2e:
+ a2e[addr] = []
+ a2e[addr].append(addr2en[p])
+ print(" %s <= %d;" % (p, addr), file=tb_f)
+ enzero = set()
+ for v in a2e.values():
+ x = random.choice(v)
+ for s in v:
+ if s != x:
+ enzero.add(s)
+ for p in tb_din:
+ val = 0 if p in enzero else random.randrange(1048576)
+ print(" %s <= %d;" % (p, val), file=tb_f)
print(" #900;", file=tb_f)
print(" end", file=tb_f)
diff --git a/tests/bram/run-single.sh b/tests/bram/run-single.sh
index 98a45b613..429a79e3c 100644
--- a/tests/bram/run-single.sh
+++ b/tests/bram/run-single.sh
@@ -1,6 +1,6 @@
#!/bin/bash
set -e
-../../yosys -qq -p "proc; opt; memory -nomap -bram temp/brams_${2}.txt; opt -fast -full" \
+../../yosys -qq -f verilog -p "proc; opt; memory -nomap -bram temp/brams_${2}.txt; opt -fast -full" \
-l temp/synth_${1}_${2}.log -o temp/synth_${1}_${2}.v temp/brams_${1}.v
iverilog -Dvcd_file=\"temp/tb_${1}_${2}.vcd\" -DSIMLIB_MEMDELAY=1 -o temp/tb_${1}_${2}.tb temp/brams_${1}_tb.v \
temp/brams_${1}_ref.v temp/synth_${1}_${2}.v temp/brams_${2}.v ../../techlibs/common/simlib.v
diff --git a/tests/memories/read_arst.v b/tests/memories/read_arst.v
new file mode 100644
index 000000000..6100cc4a7
--- /dev/null
+++ b/tests/memories/read_arst.v
@@ -0,0 +1,27 @@
+// expect-wr-ports 1
+// expect-rd-ports 1
+// expect-rd-clk \clk
+// expect-rd-en \re
+// expect-rd-arst-sig \reset
+// expect-rd-arst-val 8'01011010
+// expect-rd-init-val 8'00111100
+
+module top(input clk, input we, re, reset, input [7:0] addr, wdata, output reg [7:0] rdata);
+
+reg [7:0] bram[0:255];
+initial rdata = 8'h3c;
+
+always @(posedge clk) begin
+ if (we)
+ bram[addr] <= wdata;
+end
+
+always @(posedge clk, posedge reset) begin
+ if (reset)
+ rdata <= 8'h5a;
+ else if (re)
+ rdata <= bram[addr];
+end
+
+endmodule
+
diff --git a/tests/memories/read_two_mux.v b/tests/memories/read_two_mux.v
index 4f2e7e1cd..8b609c552 100644
--- a/tests/memories/read_two_mux.v
+++ b/tests/memories/read_two_mux.v
@@ -1,6 +1,9 @@
// expect-wr-ports 1
// expect-rd-ports 1
-// expect-no-rd-clk
+// expect-rd-clk \clk
+// expect-rd-en \re
+// expect-rd-srst-sig \reset
+// expect-rd-srst-val 8'00000000
module top(input clk, input we, re, reset, input [7:0] addr, wdata, output reg [7:0] rdata);
diff --git a/tests/memories/run-test.sh b/tests/memories/run-test.sh
index 376f5bf79..c65066a9c 100755
--- a/tests/memories/run-test.sh
+++ b/tests/memories/run-test.sh
@@ -18,11 +18,15 @@ ${MAKE:-make} -f ../tools/autotest.mk SEED="$seed" EXTRA_FLAGS="$abcopt" *.v
for f in `egrep -l 'expect-(wr-ports|rd-ports|rd-clk)' *.v`; do
echo -n "Testing expectations for $f .."
- ../../yosys -qp "proc; opt; memory -nomap;; dump -outfile ${f%.v}.dmp t:\$mem" $f
+ ../../yosys -f verilog -qp "proc; opt; memory -nomap;; dump -outfile ${f%.v}.dmp t:\$mem_v2" $f
if grep -q expect-wr-ports $f; then
grep -q "parameter \\\\WR_PORTS $(gawk '/expect-wr-ports/ { print $3; }' $f)\$" ${f%.v}.dmp ||
{ echo " ERROR: Unexpected number of write ports."; false; }
fi
+ if grep -q expect-wr-wide-continuation $f; then
+ grep -q "parameter \\\\WR_WIDE_CONTINUATION $(gawk '/expect-wr-wide-continuation/ { print $3; }' $f)\$" ${f%.v}.dmp ||
+ { echo " ERROR: Unexpected write wide continuation."; false; }
+ fi
if grep -q expect-rd-ports $f; then
grep -q "parameter \\\\RD_PORTS $(gawk '/expect-rd-ports/ { print $3; }' $f)\$" ${f%.v}.dmp ||
{ echo " ERROR: Unexpected number of read ports."; false; }
@@ -31,6 +35,34 @@ for f in `egrep -l 'expect-(wr-ports|rd-ports|rd-clk)' *.v`; do
grep -q "connect \\\\RD_CLK \\$(gawk '/expect-rd-clk/ { print $3; }' $f)\$" ${f%.v}.dmp ||
{ echo " ERROR: Unexpected read clock."; false; }
fi
+ if grep -q expect-rd-en $f; then
+ grep -q "connect \\\\RD_EN \\$(gawk '/expect-rd-en/ { print $3; }' $f)\$" ${f%.v}.dmp ||
+ { echo " ERROR: Unexpected read enable."; false; }
+ fi
+ if grep -q expect-rd-srst-sig $f; then
+ grep -q "connect \\\\RD_SRST \\$(gawk '/expect-rd-srst-sig/ { print $3; }' $f)\$" ${f%.v}.dmp ||
+ { echo " ERROR: Unexpected read sync reset."; false; }
+ fi
+ if grep -q expect-rd-srst-val $f; then
+ grep -q "parameter \\\\RD_SRST_VALUE $(gawk '/expect-rd-srst-val/ { print $3; }' $f)\$" ${f%.v}.dmp ||
+ { echo " ERROR: Unexpected read sync reset value."; false; }
+ fi
+ if grep -q expect-rd-arst-sig $f; then
+ grep -q "connect \\\\RD_ARST \\$(gawk '/expect-rd-arst-sig/ { print $3; }' $f)\$" ${f%.v}.dmp ||
+ { echo " ERROR: Unexpected read async reset."; false; }
+ fi
+ if grep -q expect-rd-arst-val $f; then
+ grep -q "parameter \\\\RD_ARST_VALUE $(gawk '/expect-rd-arst-val/ { print $3; }' $f)\$" ${f%.v}.dmp ||
+ { echo " ERROR: Unexpected read async reset value."; false; }
+ fi
+ if grep -q expect-rd-init-val $f; then
+ grep -q "parameter \\\\RD_INIT_VALUE $(gawk '/expect-rd-init-val/ { print $3; }' $f)\$" ${f%.v}.dmp ||
+ { echo " ERROR: Unexpected read init value."; false; }
+ fi
+ if grep -q expect-rd-wide-continuation $f; then
+ grep -q "parameter \\\\RD_WIDE_CONTINUATION $(gawk '/expect-rd-wide-continuation/ { print $3; }' $f)\$" ${f%.v}.dmp ||
+ { echo " ERROR: Unexpected read wide continuation."; false; }
+ fi
if grep -q expect-no-rd-clk $f; then
grep -q "connect \\\\RD_CLK 1'x\$" ${f%.v}.dmp ||
{ echo " ERROR: Expected no read clock."; false; }
diff --git a/tests/memories/trans_addr_enable.v b/tests/memories/trans_addr_enable.v
new file mode 100644
index 000000000..f366f41ad
--- /dev/null
+++ b/tests/memories/trans_addr_enable.v
@@ -0,0 +1,21 @@
+// expect-wr-ports 1
+// expect-rd-ports 1
+// expect-rd-clk \clk
+
+module top(input clk, we, rae, input [7:0] addr, wd, output [7:0] rd);
+
+reg [7:0] mem[0:255];
+
+reg [7:0] rra;
+
+always @(posedge clk) begin
+ if (we)
+ mem[addr] <= wd;
+
+ if (rae)
+ rra <= addr;
+end
+
+assign rd = mem[rra];
+
+endmodule
diff --git a/tests/memories/trans_sdp.v b/tests/memories/trans_sdp.v
new file mode 100644
index 000000000..b89f2ccf0
--- /dev/null
+++ b/tests/memories/trans_sdp.v
@@ -0,0 +1,21 @@
+// expect-wr-ports 1
+// expect-rd-ports 1
+// expect-rd-clk \clk
+// expect-rd-en \re
+
+module top(input clk, we, re, input [7:0] ra, wa, wd, output reg [7:0] rd);
+
+reg [7:0] mem[0:255];
+
+always @(posedge clk) begin
+ if (we)
+ mem[wa] <= wd;
+
+ if (re) begin
+ rd <= mem[ra];
+ if (we && ra == wa)
+ rd <= wd;
+ end
+end
+
+endmodule
diff --git a/tests/memories/trans_sp.v b/tests/memories/trans_sp.v
new file mode 100644
index 000000000..ddd41a13e
--- /dev/null
+++ b/tests/memories/trans_sp.v
@@ -0,0 +1,21 @@
+// expect-wr-ports 1
+// expect-rd-ports 1
+// expect-rd-clk \clk
+// expect-rd-en \re
+
+module top(input clk, we, re, input [7:0] addr, wd, output reg [7:0] rd);
+
+reg [7:0] mem[0:255];
+
+always @(posedge clk) begin
+ if (we)
+ mem[addr] <= wd;
+
+ if (re) begin
+ rd <= mem[addr];
+ if (we)
+ rd <= wd;
+ end
+end
+
+endmodule
diff --git a/tests/memories/wide_all.v b/tests/memories/wide_all.v
new file mode 100644
index 000000000..f7bc3e5ce
--- /dev/null
+++ b/tests/memories/wide_all.v
@@ -0,0 +1,36 @@
+// expect-wr-ports 2
+// expect-rd-ports 1
+// expect-wr-wide-continuation 2'10
+
+module test(
+ input clk,
+ input [3:0] we,
+ input [6:0] ra,
+ input [5:0] wa,
+ input [31:0] wd,
+ output [15:0] rd
+);
+
+reg [7:0] mem[3:254];
+
+assign rd[7:0] = mem[{ra, 1'b0}];
+assign rd[15:0] = mem[{ra, 1'b1}];
+
+initial begin
+ mem[5] = 8'h12;
+ mem[6] = 8'h34;
+ mem[7] = 8'h56;
+end
+
+always @(posedge clk) begin
+ if (we[0])
+ mem[{wa, 2'b00}] <= wd[7:0];
+ if (we[1])
+ mem[{wa, 2'b01}] <= wd[15:8];
+ if (we[2])
+ mem[{wa, 2'b10}] <= wd[23:16];
+ if (we[3])
+ mem[{wa, 2'b11}] <= wd[31:24];
+end
+
+endmodule
diff --git a/tests/memories/wide_read_async.v b/tests/memories/wide_read_async.v
new file mode 100644
index 000000000..aecdb1938
--- /dev/null
+++ b/tests/memories/wide_read_async.v
@@ -0,0 +1,27 @@
+// expect-wr-ports 1
+// expect-rd-ports 4
+// expect-rd-wide-continuation 4'1110
+
+module test(
+ input clk,
+ input we,
+ input [5:0] ra,
+ input [7:0] wa,
+ input [7:0] wd,
+ output [31:0] rd
+);
+
+reg [7:0] mem[0:255];
+
+assign rd[7:0] = mem[{ra, 2'b00}];
+assign rd[15:8] = mem[{ra, 2'b01}];
+assign rd[23:16] = mem[{ra, 2'b10}];
+assign rd[31:24] = mem[{ra, 2'b11}];
+
+always @(posedge clk) begin
+ if (we)
+ mem[wa] <= wd;
+end
+
+endmodule
+
diff --git a/tests/memories/wide_read_mixed.v b/tests/memories/wide_read_mixed.v
new file mode 100644
index 000000000..c36db3d31
--- /dev/null
+++ b/tests/memories/wide_read_mixed.v
@@ -0,0 +1,46 @@
+// expect-wr-ports 1
+// expect-rd-ports 4
+// expect-rd-wide-continuation 4'1110
+// expect-rd-srst-val 32'10000111011001010100001100100001
+// expect-rd-init-val 32'10101011110011011110111110101011
+
+// In this testcase, the byte-wide read ports are merged into a single
+// word-wide port despite mismatched transparency, with soft transparency
+// logic inserted on half the port to preserve the semantics.
+
+module test(
+ input clk,
+ input re, rr,
+ input we,
+ input [5:0] ra,
+ input [7:0] wa,
+ input [7:0] wd,
+ output reg [31:0] rd
+);
+
+reg [7:0] mem[0:255];
+
+initial rd = 32'habcdefab;
+
+always @(posedge clk) begin
+ if (rr) begin
+ rd <= 32'h87654321;
+ end else if (re) begin
+ rd[7:0] <= mem[{ra, 2'b00}];
+ rd[15:8] <= mem[{ra, 2'b01}];
+ rd[23:16] <= mem[{ra, 2'b10}];
+ rd[31:24] <= mem[{ra, 2'b11}];
+ if (we && wa == {ra, 2'b00})
+ rd [7:0] <= wd;
+ if (we && wa == {ra, 2'b01})
+ rd [15:8] <= wd;
+ end
+end
+
+always @(posedge clk) begin
+ if (we)
+ mem[wa] <= wd;
+end
+
+endmodule
+
diff --git a/tests/memories/wide_read_sync.v b/tests/memories/wide_read_sync.v
new file mode 100644
index 000000000..54ba3f256
--- /dev/null
+++ b/tests/memories/wide_read_sync.v
@@ -0,0 +1,32 @@
+// expect-wr-ports 1
+// expect-rd-ports 4
+// expect-rd-wide-continuation 4'1110
+
+module test(
+ input clk,
+ input re,
+ input we,
+ input [5:0] ra,
+ input [7:0] wa,
+ input [7:0] wd,
+ output reg [31:0] rd
+);
+
+reg [7:0] mem[0:255];
+
+always @(posedge clk) begin
+ if (re) begin
+ rd[7:0] <= mem[{ra, 2'b00}];
+ rd[15:8] <= mem[{ra, 2'b01}];
+ rd[23:16] <= mem[{ra, 2'b10}];
+ rd[31:24] <= mem[{ra, 2'b11}];
+ end
+end
+
+always @(posedge clk) begin
+ if (we)
+ mem[wa] <= wd;
+end
+
+endmodule
+
diff --git a/tests/memories/wide_read_trans.v b/tests/memories/wide_read_trans.v
new file mode 100644
index 000000000..fe3293500
--- /dev/null
+++ b/tests/memories/wide_read_trans.v
@@ -0,0 +1,40 @@
+// expect-wr-ports 1
+// expect-rd-ports 4
+// expect-rd-wide-continuation 4'1110
+
+module test(
+ input clk,
+ input re,
+ input we,
+ input [5:0] ra,
+ input [7:0] wa,
+ input [7:0] wd,
+ output reg [31:0] rd
+);
+
+reg [7:0] mem[0:255];
+
+always @(posedge clk) begin
+ if (re) begin
+ rd[7:0] <= mem[{ra, 2'b00}];
+ rd[15:8] <= mem[{ra, 2'b01}];
+ rd[23:16] <= mem[{ra, 2'b10}];
+ rd[31:24] <= mem[{ra, 2'b11}];
+ if (we && wa == {ra, 2'b00})
+ rd [7:0] <= wd;
+ if (we && wa == {ra, 2'b01})
+ rd [15:8] <= wd;
+ if (we && wa == {ra, 2'b10})
+ rd [23:16] <= wd;
+ if (we && wa == {ra, 2'b11})
+ rd [31:24] <= wd;
+ end
+end
+
+always @(posedge clk) begin
+ if (we)
+ mem[wa] <= wd;
+end
+
+endmodule
+
diff --git a/tests/memories/wide_thru_priority.v b/tests/memories/wide_thru_priority.v
new file mode 100644
index 000000000..10c0d837b
--- /dev/null
+++ b/tests/memories/wide_thru_priority.v
@@ -0,0 +1,29 @@
+// expect-wr-ports 3
+// expect-rd-ports 1
+// expect-wr-wide-continuation 3'010
+
+module test(
+ input clk,
+ input we1, we2,
+ input [5:0] ra,
+ input [4:0] wa1,
+ input [5:0] wa2,
+ input [15:0] wd1,
+ input [7:0] wd2,
+ output [7:0] rd
+);
+
+reg [7:0] mem[0:63];
+
+assign rd = mem[ra];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[{wa1, 1'b0}] <= wd1[7:0];
+ if (we2)
+ mem[wa2] <= wd2;
+ if (we1)
+ mem[{wa1, 1'b1}] <= wd1[15:8];
+end
+
+endmodule
diff --git a/tests/memories/wide_write.v b/tests/memories/wide_write.v
new file mode 100644
index 000000000..5c4cc41f9
--- /dev/null
+++ b/tests/memories/wide_write.v
@@ -0,0 +1,29 @@
+// expect-wr-ports 4
+// expect-rd-ports 1
+// expect-wr-wide-continuation 4'1110
+
+module test(
+ input clk,
+ input [3:0] we,
+ input [7:0] ra,
+ input [5:0] wa,
+ input [31:0] wd,
+ output [7:0] rd
+);
+
+reg [7:0] mem[0:255];
+
+assign rd = mem[ra];
+
+always @(posedge clk) begin
+ if (we[0])
+ mem[{wa, 2'b00}] <= wd[7:0];
+ if (we[1])
+ mem[{wa, 2'b01}] <= wd[15:8];
+ if (we[2])
+ mem[{wa, 2'b10}] <= wd[23:16];
+ if (we[3])
+ mem[{wa, 2'b11}] <= wd[31:24];
+end
+
+endmodule
diff --git a/tests/opt/bug1854.ys b/tests/opt/bug1854.ys
new file mode 100644
index 000000000..00a36ae94
--- /dev/null
+++ b/tests/opt/bug1854.ys
@@ -0,0 +1,17 @@
+read_verilog << EOT
+module top(input clk, input [3:0] addr, output reg [0:0] dout);
+ reg [1:0] mem[0:15];
+ initial begin
+ mem[0] = 2'b00;
+ mem[1] = 2'b01;
+ mem[2] = 2'b10;
+ mem[3] = 2'b11;
+ end
+ always @(posedge clk)
+ dout <= mem[addr];
+endmodule
+EOT
+
+prep -rdff
+
+select -assert-none t:$dff
diff --git a/tests/opt/bug2623.ys b/tests/opt/bug2623.ys
new file mode 100644
index 000000000..2ff23ea6f
--- /dev/null
+++ b/tests/opt/bug2623.ys
@@ -0,0 +1,14 @@
+read_rtlil << EOT
+
+module \top
+ wire output 1 \a
+ wire width 0 $dummy
+ cell \abc \abc
+ connect \a \a
+ connect \b $dummy
+ end
+end
+
+EOT
+
+opt_clean
diff --git a/tests/opt/bug2765.ys b/tests/opt/bug2765.ys
new file mode 100644
index 000000000..7cb790bd7
--- /dev/null
+++ b/tests/opt/bug2765.ys
@@ -0,0 +1,34 @@
+read_verilog << EOT
+
+module top(...);
+
+input clk;
+input [3:0] wa;
+input [15:0] wd;
+input [3:0] ra;
+output [15:0] rd;
+
+reg [15:0] mem[0:15];
+
+integer i;
+reg x;
+
+always @(posedge clk) begin
+ for (i = 0; i < 2; i = i + 1) begin
+ x = i == 1;
+ if (x)
+ mem[wa] <= wd;
+ end
+end
+
+assign rd = mem[ra];
+
+endmodule
+
+EOT
+
+proc
+opt
+select -assert-count 2 t:$memwr_v2
+opt_mem
+select -assert-count 1 t:$memwr_v2
diff --git a/tests/opt/bug2766.ys b/tests/opt/bug2766.ys
new file mode 100644
index 000000000..c7aa916f4
--- /dev/null
+++ b/tests/opt/bug2766.ys
@@ -0,0 +1,101 @@
+# Case 1.
+
+read_verilog << EOT
+
+module top(...);
+
+input clk;
+input sel;
+input [3:0] ra;
+input [3:0] wa;
+input wd;
+output [3:0] rd;
+
+reg [3:0] mem[0:15];
+
+integer i;
+initial begin
+ for (i = 0; i < 16; i = i + 1)
+ mem[i] <= i;
+end
+
+assign rd = mem[ra];
+
+always @(posedge clk) begin
+ mem[wa] <= {4{sel ? wd : mem[wa][0]}};
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_clean
+
+design -save start
+memory_map
+design -save preopt
+
+design -load start
+opt_mem_feedback
+memory_map
+design -save postopt
+
+equiv_opt -assert -run prepare: :
+
+
+
+design -reset
+
+# Case 2.
+
+read_verilog << EOT
+
+module top(...);
+
+input clk;
+input s1;
+input s2;
+input s3;
+input [3:0] ra;
+input [3:0] wa;
+input wd;
+output rd;
+
+reg mem[0:15];
+
+integer i;
+initial begin
+ for (i = 0; i < 16; i = i + 1)
+ mem[i] <= ^i;
+end
+
+assign rd = mem[ra];
+
+wire ta = s1 ? wd : mem[wa];
+wire tb = s2 ? wd : ta;
+wire tc = s3 ? tb : ta;
+
+always @(posedge clk) begin
+ mem[wa] <= tc;
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_clean
+
+design -save start
+memory_map
+design -save preopt
+
+design -load start
+opt_mem_feedback
+memory_map
+design -save postopt
+
+equiv_opt -assert -run prepare: :
diff --git a/tests/opt/bug2824.ys b/tests/opt/bug2824.ys
new file mode 100644
index 000000000..9d0d1e9e5
--- /dev/null
+++ b/tests/opt/bug2824.ys
@@ -0,0 +1,7 @@
+read_verilog -icells << EOT
+module top(input I, output O);
+$pmux #(.WIDTH(1), .S_WIDTH(2)) m (.S({I, 1'b0}), .A(1'b0), .B({I, 1'b0}), .Y(O));
+endmodule
+EOT
+
+equiv_opt -assert opt_muxtree
diff --git a/tests/opt/bug2920.ys b/tests/opt/bug2920.ys
new file mode 100644
index 000000000..a8281a73a
--- /dev/null
+++ b/tests/opt/bug2920.ys
@@ -0,0 +1,42 @@
+read_ilang <<EOT
+
+module \mod
+ wire input 1 \clk
+ attribute \init 2'00
+ wire width 2 $q1
+ attribute \init 2'00
+ wire width 2 $q2
+ wire output 2 width 4 \q
+ cell $dff $ff1
+ parameter \CLK_POLARITY 1'1
+ parameter \WIDTH 1
+ connect \CLK \clk
+ connect \D 1'0
+ connect \Q $q1 [0]
+ end
+ cell $dff $ff2
+ parameter \CLK_POLARITY 1'1
+ parameter \WIDTH 1
+ connect \CLK \clk
+ connect \D 1'0
+ connect \Q $q2 [0]
+ end
+ cell $dff $ff3
+ parameter \CLK_POLARITY 1'1
+ parameter \WIDTH 2
+ connect \CLK \clk
+ connect \D 2'00
+ connect \Q { $q1 [1] $q2 [1] }
+ end
+ connect \q [0] $q1 [0]
+ connect \q [1] $q2 [0]
+ connect \q [2] $q1 [1]
+ connect \q [3] $q2 [1]
+end
+
+EOT
+
+opt_clean
+opt_merge
+opt_dff
+opt_clean
diff --git a/tests/opt/bug3047.ys b/tests/opt/bug3047.ys
new file mode 100644
index 000000000..6713877ce
--- /dev/null
+++ b/tests/opt/bug3047.ys
@@ -0,0 +1,12 @@
+read_verilog << EOT
+
+module test (A, B, C, D, Y);
+ input A, B, C, D;
+ output Y;
+ assign Y = A^B^C^D^A;
+endmodule
+
+EOT
+
+techmap
+equiv_opt -assert extract_reduce
diff --git a/tests/opt/bug3117.ys b/tests/opt/bug3117.ys
new file mode 100644
index 000000000..177b3ab9a
--- /dev/null
+++ b/tests/opt/bug3117.ys
@@ -0,0 +1,34 @@
+read_verilog << EOT
+
+module test (...);
+
+input [7:1] wa1;
+input [7:1] wa2;
+input [7:0] ra;
+output [7:0] rd;
+input clk;
+input we1, we2;
+input [15:0] wd1, wd2;
+
+reg [7:0] mem [0:255];
+
+assign rd = mem[ra];
+
+always @(posedge clk) begin
+ if (we1) begin
+ mem[{wa1, 1'b0}] <= wd1[7:0];
+ mem[{wa1, 1'b1}] <= wd1[15:8];
+ end else begin
+ mem[{wa2, 1'b0}] <= wd2[7:0];
+ mem[{wa2, 1'b1}] <= wd2[15:8];
+ end
+end
+
+endmodule
+
+EOT
+
+proc
+opt
+memory_share
+select -assert-count 1 t:$memwr_v2
diff --git a/tests/opt/memory_dff_trans.ys b/tests/opt/memory_dff_trans.ys
new file mode 100644
index 000000000..102b36f26
--- /dev/null
+++ b/tests/opt/memory_dff_trans.ys
@@ -0,0 +1,874 @@
+# Good case 1: single port.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] addr,
+ input [3:0] wd,
+ input we,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] mem[0:15];
+
+always @(posedge clk) begin
+ if (we) begin
+ mem[addr] <= wd;
+ rd <= wd;
+ end else begin
+ rd <= mem[addr];
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+memory_dff
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=1'b1 r:RD_COLLISION_X_MASK=1'b0 %i %i
+
+design -reset
+
+# Good case 2: single port, exclusive.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] addr,
+ input [3:0] wd,
+ input we,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] mem[0:15];
+
+always @(posedge clk) begin
+ if (we) begin
+ mem[addr] <= wd;
+ end else begin
+ rd <= mem[addr];
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+memory_dff
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=1'b0 r:RD_COLLISION_X_MASK=1'b1 %i %i
+
+design -reset
+
+# Good case 3: proper bypass muxes.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] ra,
+ input [3:0] wa1,
+ input [3:0] wa2,
+ input [3:0] wd1,
+ input [3:0] wd2,
+ input we1, we2,
+ input re,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] mem[0:15];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2)
+ mem[wa2] <= wd2;
+ if (re) begin
+ rd <= mem[ra];
+ if (we1 && wa1 == ra)
+ rd <= wd1;
+ if (we2 && wa2 == ra)
+ rd <= wd2;
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+memory_dff
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=2'b11 r:RD_COLLISION_X_MASK=2'b00 %i %i
+
+design -reset
+
+# Good case 4: proper bypass mux, but only one.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] ra,
+ input [3:0] wa1,
+ input [3:0] wa2,
+ input [3:0] wd1,
+ input [3:0] wd2,
+ input we1, we2,
+ input re,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] mem[0:15];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2)
+ mem[wa2] <= wd2;
+ if (re) begin
+ rd <= mem[ra];
+ if (we1 && wa1 == ra)
+ rd <= wd1;
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+memory_dff
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=2'b01 r:RD_COLLISION_X_MASK=2'b00 %i %i
+
+design -reset
+
+# Good case 5: proper bypass mux, but the other one.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] ra,
+ input [3:0] wa1,
+ input [3:0] wa2,
+ input [3:0] wd1,
+ input [3:0] wd2,
+ input we1, we2,
+ input re,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] mem[0:15];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2)
+ mem[wa2] <= wd2;
+ if (re) begin
+ rd <= mem[ra];
+ if (we2 && wa2 == ra)
+ rd <= wd2;
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+memory_dff
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=2'b10 r:RD_COLLISION_X_MASK=2'b00 %i %i
+
+design -reset
+
+# Good case 6: 'x mux.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] ra,
+ input [3:0] wa1,
+ input [3:0] wa2,
+ input [3:0] wd1,
+ input [3:0] wd2,
+ input we1, we2,
+ input re,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] mem[0:15];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2)
+ mem[wa2] <= wd2;
+ if (re) begin
+ rd <= mem[ra];
+ if (we1 && wa1 == ra)
+ rd <= 4'hx;
+ if (we2 && wa2 == ra)
+ rd <= wd2;
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+memory_dff
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=2'b10 r:RD_COLLISION_X_MASK=2'b01 %i %i
+
+design -reset
+
+# Good case 7: uncollidable addresses.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] addr,
+ input [3:0] wd1,
+ input [3:0] wd2,
+ input we1, we2,
+ input re,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] mem[0:15];
+
+wire [3:0] wa1 = addr;
+wire [3:0] wa2 = addr + 1;
+wire [3:0] ra = addr + 2;
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2)
+ mem[wa2] <= wd2;
+ if (re) begin
+ rd <= mem[ra];
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+memory_dff
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=2'b00 r:RD_COLLISION_X_MASK=2'b11 %i %i
+
+design -reset
+
+# Good case 8: uncollidable addresses, but still have soft transparency logic.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] addr,
+ input [3:0] wd1,
+ input [3:0] wd2,
+ input we1, we2,
+ input re,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] mem[0:15];
+
+wire [3:0] wa1 = addr;
+wire [3:0] wa2 = addr + 1;
+wire [3:0] ra = addr + 2;
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2)
+ mem[wa2] <= wd2;
+ if (re) begin
+ rd <= mem[ra];
+ if (we1 && wa1 == ra)
+ rd <= wd1;
+ if (we2 && wa2 == ra)
+ rd <= wd2;
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+memory_dff
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=2'b00 r:RD_COLLISION_X_MASK=2'b11 %i %i
+
+design -reset
+
+# Bad case 1: broken bypass signal.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] ra,
+ input [3:0] wa1,
+ input [3:0] wa2,
+ input [3:0] wd1,
+ input [3:0] wd2,
+ input we1, we2,
+ input re,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] mem[0:15];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2)
+ mem[wa2] <= wd2;
+ if (re) begin
+ rd <= mem[ra];
+ if (we1 && wa1 == ra)
+ rd <= wd1;
+ if (we2 && wa2 == ra && we1)
+ rd <= wd2;
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+logger -expect log "FF found, but with a mux select that doesn't seem to correspond to transparency logic" 1
+memory_dff
+logger -check-expected
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_CLK_ENABLE=1'b0 %i
+
+design -reset
+
+# Bad case 2: bad data signal.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] ra,
+ input [3:0] wa1,
+ input [3:0] wa2,
+ input [3:0] wd1,
+ input [3:0] wd2,
+ input we1, we2,
+ input re,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] mem[0:15];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2)
+ mem[wa2] <= wd2;
+ if (re) begin
+ rd <= mem[ra];
+ if (we1 && wa1 == ra)
+ rd <= wd1;
+ if (we2 && wa2 == ra)
+ rd <= wd1;
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+logger -expect log "FF found, but with a mux data input that doesn't seem to correspond to transparency logic" 1
+memory_dff
+logger -check-expected
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_CLK_ENABLE=1'b0 %i
+
+design -reset
+
+# Bad case 3: priority mismatch.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] ra,
+ input [3:0] wa1,
+ input [3:0] wa2,
+ input [3:0] wd1,
+ input [3:0] wd2,
+ input we1, we2,
+ input re,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] mem[0:15];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2)
+ mem[wa2] <= wd2;
+ if (re) begin
+ rd <= mem[ra];
+ if (we2 && wa2 == ra)
+ rd <= wd2;
+ if (we1 && wa1 == ra)
+ rd <= wd1;
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+logger -expect log "FF found, but transparency logic priority doesn't match write priority." 1
+memory_dff
+logger -check-expected
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_CLK_ENABLE=1'b0 %i
+
+design -reset
+
+# Good case 10: priority mismatch, but since the second value is 'x, it's still OK.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] ra,
+ input [3:0] wa1,
+ input [3:0] wa2,
+ input [3:0] wd1,
+ input [3:0] wd2,
+ input we1, we2,
+ input re,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] mem[0:15];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2)
+ mem[wa2] <= wd2;
+ if (re) begin
+ rd <= mem[ra];
+ if (we2 && wa2 == ra)
+ rd <= wd2;
+ if (we1 && wa1 == ra)
+ rd <= 4'hx;
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+memory_dff
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=2'b10 r:RD_COLLISION_X_MASK=2'b01 %i %i
+
+design -reset
+
+# Good case 11: priority mismatch, but since three-way collision cannot happen, it's still OK.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] addr,
+ input [1:0] mode,
+ input [3:0] wd1,
+ input [3:0] wd2,
+ input we1, we2,
+ input re,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] wa1, wa2, ra;
+
+always @* begin
+ case (mode)
+ 0: begin
+ wa1 = addr+1;
+ wa2 = addr;
+ ra = addr;
+ end
+ 1: begin
+ wa1 = addr;
+ wa2 = addr+1;
+ ra = addr;
+ end
+ 2: begin
+ wa1 = addr;
+ wa2 = addr;
+ ra = addr+1;
+ end
+ 3: begin
+ wa1 = addr;
+ wa2 = addr+1;
+ ra = addr+2;
+ end
+ endcase
+end
+
+reg [3:0] mem[0:15];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2)
+ mem[wa2] <= wd2;
+ if (re) begin
+ rd <= mem[ra];
+ if (we2 && wa2 == ra)
+ rd <= wd2;
+ if (we1 && wa1 == ra)
+ rd <= wd1;
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+memory_dff
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=2'b11 r:RD_COLLISION_X_MASK=2'b00 %i %i
+
+design -reset
+
+# Bad case 4: half of the port is transparent.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] ra,
+ input [3:0] wa1,
+ input [3:0] wa2,
+ input [3:0] wd1,
+ input [3:0] wd2,
+ input we1, we2,
+ input re,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] mem[0:15];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2)
+ mem[wa2] <= wd2;
+ if (re) begin
+ rd <= mem[ra];
+ if (we1 && wa1 == ra)
+ rd <= wd1;
+ if (we2 && wa2 == ra)
+ rd[3:2] <= wd2[3:2];
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+logger -expect log "FF found, but soft transparency logic is inconsistent for port 1." 1
+memory_dff
+logger -check-expected
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_CLK_ENABLE=1'b0 %i
+
+design -reset
+
+# Good case 12: like above, but the other bits aren't changed by the port anyway.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] ra,
+ input [3:0] wa1,
+ input [3:0] wa2,
+ input [3:0] wd1,
+ input [3:0] wd2,
+ input we1, we2,
+ input re,
+ input clk,
+ output reg [3:0] rd,
+);
+
+reg [3:0] mem[0:15];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2)
+ mem[wa2][3:2] <= wd2[3:2];
+ if (re) begin
+ rd <= mem[ra];
+ if (we1 && wa1 == ra)
+ rd <= wd1;
+ if (we2 && wa2 == ra)
+ rd[3:2] <= wd2[3:2];
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+memory_dff
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=2'b11 r:RD_COLLISION_X_MASK=2'b00 %i %i
+
+design -reset
+
+# Good case 13: wide read, narrow write.
+
+read_verilog << EOT
+
+module top(
+ input [7:0] addr,
+ input [7:0] wd,
+ input we,
+ input re,
+ input clk,
+ output reg [31:0] rd,
+);
+
+reg [7:0] mem[0:255];
+
+always @(posedge clk) begin
+ if (we)
+ mem[addr] <= wd;
+ if (re) begin
+ rd[7:0] <= mem[{addr[7:2], 2'b00}];
+ rd[15:8] <= mem[{addr[7:2], 2'b01}];
+ rd[23:16] <= mem[{addr[7:2], 2'b10}];
+ rd[31:24] <= mem[{addr[7:2], 2'b11}];
+ case ({we, addr[1:0]})
+ 3'b100: rd[7:0] <= wd;
+ 3'b101: rd[15:8] <= wd;
+ 3'b110: rd[23:16] <= wd;
+ 3'b111: rd[31:24] <= wd;
+ endcase
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+dump
+memory_dff
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=4'b1111 r:RD_COLLISION_X_MASK=4'b0000 %i %i
+memory_share
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=4'b1111 r:RD_COLLISION_X_MASK=4'b0000 %i %i
+select -assert-count 1 t:$mem_v2 r:RD_WIDE_CONTINUATION=4'b1110 %i
+
+design -reset
+
+# Good case 14: narrow read, wide write.
+
+read_verilog << EOT
+
+module top(
+ input [7:0] addr,
+ input [31:0] wd,
+ input we,
+ input re,
+ input clk,
+ output reg [7:0] rd,
+);
+
+reg [7:0] mem[0:255];
+
+always @(posedge clk) begin
+ if (we) begin
+ mem[{addr[7:2], 2'b00}] <= wd[7:0];
+ mem[{addr[7:2], 2'b01}] <= wd[15:8];
+ mem[{addr[7:2], 2'b10}] <= wd[23:16];
+ mem[{addr[7:2], 2'b11}] <= wd[31:24];
+ end
+ if (re) begin
+ rd <= mem[addr];
+ case ({we, addr[1:0]})
+ 3'b100: rd <= wd[7:0];
+ 3'b101: rd <= wd[15:8];
+ 3'b110: rd <= wd[23:16];
+ 3'b111: rd <= wd[31:24];
+ endcase
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+dump
+memory_dff
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=4'b1111 r:RD_COLLISION_X_MASK=4'b0000 %i %i
+memory_share
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:RD_TRANSPARENCY_MASK=4'b1111 r:RD_COLLISION_X_MASK=4'b0000 %i %i
+select -assert-count 1 t:$mem_v2 r:WR_WIDE_CONTINUATION=4'b1110 %i
+
+design -reset
+
+# Good case 15: wide read, wide write.
+
+read_verilog << EOT
+
+module top(
+ input [7:0] addr,
+ input [31:0] wd,
+ input we,
+ input re,
+ input clk,
+ output reg [31:0] rd,
+);
+
+reg [7:0] mem[0:255];
+
+always @(posedge clk) begin
+ if (we) begin
+ mem[{addr[7:2], 2'b00}] <= wd[7:0];
+ mem[{addr[7:2], 2'b01}] <= wd[15:8];
+ mem[{addr[7:2], 2'b10}] <= wd[23:16];
+ mem[{addr[7:2], 2'b11}] <= wd[31:24];
+ end
+ if (re) begin
+ rd[7:0] <= mem[{addr[7:2], 2'b00}];
+ rd[15:8] <= mem[{addr[7:2], 2'b01}];
+ rd[23:16] <= mem[{addr[7:2], 2'b10}];
+ rd[31:24] <= mem[{addr[7:2], 2'b11}];
+ if (we)
+ rd <= wd;
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_dff
+opt_clean
+dump
+memory_dff
+select -assert-count 4 t:$memrd_v2
+select -assert-count 1 t:$memrd_v2 r:TRANSPARENCY_MASK=4'b0001 r:COLLISION_X_MASK=4'b1110 %i %i
+select -assert-count 1 t:$memrd_v2 r:TRANSPARENCY_MASK=4'b0010 r:COLLISION_X_MASK=4'b1101 %i %i
+select -assert-count 1 t:$memrd_v2 r:TRANSPARENCY_MASK=4'b0100 r:COLLISION_X_MASK=4'b1011 %i %i
+select -assert-count 1 t:$memrd_v2 r:TRANSPARENCY_MASK=4'b1000 r:COLLISION_X_MASK=4'b0111 %i %i
+memory_share
+select -assert-count 1 t:$memrd_v2
+select -assert-count 1 t:$memwr_v2
+select -assert-count 1 t:$memrd_v2 r:TRANSPARENCY_MASK=1'b1 r:COLLISION_X_MASK=1'b0 %i %i
+
+design -reset
diff --git a/tests/opt/memory_map_offset.ys b/tests/opt/memory_map_offset.ys
new file mode 100644
index 000000000..06969922d
--- /dev/null
+++ b/tests/opt/memory_map_offset.ys
@@ -0,0 +1,100 @@
+read_verilog << EOT
+
+module top(...);
+
+input [3:0] ra;
+input [3:0] wa;
+
+input [15:0] wd;
+output [15:0] rd;
+input en, clk;
+
+reg [15:0] mem[3:9];
+
+always @(posedge clk)
+ if (en)
+ mem[wa] <= wd;
+
+assign rd = mem[ra];
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_clean
+memory_map
+
+design -stash gate
+
+read_verilog << EOT
+
+module top(...);
+
+input [3:0] ra;
+input [3:0] wa;
+
+input [15:0] wd;
+output reg [15:0] rd;
+input en, clk;
+
+reg [15:0] \mem[3] ;
+reg [15:0] \mem[4] ;
+reg [15:0] \mem[5] ;
+reg [15:0] \mem[6] ;
+reg [15:0] \mem[7] ;
+reg [15:0] \mem[8] ;
+reg [15:0] \mem[9] ;
+
+always @(posedge clk) begin
+ if (en && wa == 3)
+ \mem[3] <= wd;
+ if (en && wa == 4)
+ \mem[4] <= wd;
+ if (en && wa == 5)
+ \mem[5] <= wd;
+ if (en && wa == 6)
+ \mem[6] <= wd;
+ if (en && wa == 7)
+ \mem[7] <= wd;
+ if (en && wa == 8)
+ \mem[8] <= wd;
+ if (en && wa == 9)
+ \mem[9] <= wd;
+end
+
+always @* begin
+ rd = 16'bx;
+ if (ra == 3)
+ rd = \mem[3] ;
+ if (ra == 4)
+ rd = \mem[4] ;
+ if (ra == 5)
+ rd = \mem[5] ;
+ if (ra == 6)
+ rd = \mem[6] ;
+ if (ra == 7)
+ rd = \mem[7] ;
+ if (ra == 8)
+ rd = \mem[8] ;
+ if (ra == 9)
+ rd = \mem[9] ;
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_clean
+
+design -stash gold
+
+design -copy-from gold -as gold A:top
+design -copy-from gate -as gate A:top
+
+equiv_make gold gate equiv
+equiv_induct -undef equiv
+equiv_status -assert equiv
diff --git a/tests/opt/opt_clean_init.ys b/tests/opt/opt_clean_init.ys
index 0d567608d..7933f3e17 100644
--- a/tests/opt/opt_clean_init.ys
+++ b/tests/opt/opt_clean_init.ys
@@ -1,13 +1,22 @@
-logger -expect warning "Initial value conflict for \\y resolving to 1'0 but with init 1'1" 1
-logger -expect-no-warnings
-read_verilog <<EOT
-module top;
-(* init=1'b0 *) wire w = 1'b0;
-(* init=1'bx *) wire x = 1'b0;
-(* init=1'b1 *) wire y = 1'b0;
-(* init=1'b0 *) wire z = 1'bx;
+read_verilog << EOT
+module top(...);
+
+input [1:0] D;
+input C;
+output O;
+reg [1:0] Q;
+
+initial Q = 0;
+
+always @(posedge C)
+ Q <= D;
+
+assign O = Q[1];
+
endmodule
EOT
-clean
-select -assert-count 1 a:init
-select -assert-count 1 w:y a:init %i
+
+synth
+check -assert -initdrv
+
+select -assert-count 1 a:init=2'b0x
diff --git a/tests/opt/opt_clean_mem.ys b/tests/opt/opt_clean_mem.ys
index b35b15871..71f9e0d7b 100644
--- a/tests/opt/opt_clean_mem.ys
+++ b/tests/opt/opt_clean_mem.ys
@@ -22,28 +22,27 @@ endmodule
EOT
proc
-memory_dff
select -assert-count 2 t:$memrd
-select -assert-count 1 t:$memwr
-select -assert-count 1 t:$meminit
+select -assert-count 1 t:$memwr_v2
+select -assert-count 1 t:$meminit_v2
design -save orig
opt_clean
select -assert-none t:$memrd
-select -assert-none t:$memwr
-select -assert-none t:$meminit
+select -assert-none t:$memwr_v2
+select -assert-none t:$meminit_v2
design -load orig
expose top/rd1
opt_clean
select -assert-count 1 t:$memrd
-select -assert-count 1 t:$memwr
-select -assert-count 1 t:$meminit
+select -assert-count 1 t:$memwr_v2
+select -assert-count 1 t:$meminit_v2
design -load orig
expose top/rd1 top/rd2
opt_clean
select -assert-count 2 t:$memrd
-select -assert-count 1 t:$memwr
-select -assert-count 1 t:$meminit
+select -assert-count 1 t:$memwr_v2
+select -assert-count 1 t:$meminit_v2
diff --git a/tests/opt/opt_dff_sr.ys b/tests/opt/opt_dff_sr.ys
index daedb115c..0961cb11e 100644
--- a/tests/opt/opt_dff_sr.ys
+++ b/tests/opt/opt_dff_sr.ys
@@ -22,8 +22,10 @@ EOT
design -save orig
-equiv_opt -undef -assert -multiclock opt_dff
-design -load postopt
+# Equivalence check will fail for unmapped adlatch and dlatchsr due to negative hold hack.
+#equiv_opt -undef -assert -multiclock opt_dff
+#design -load postopt
+opt_dff
select -assert-count 1 t:$dffsr
select -assert-count 1 t:$dffsr r:WIDTH=2 %i
select -assert-count 1 t:$dffsre
@@ -34,8 +36,9 @@ select -assert-none t:$sr
design -load orig
-equiv_opt -undef -assert -multiclock opt_dff -keepdc
-design -load postopt
+#equiv_opt -undef -assert -multiclock opt_dff -keepdc
+#design -load postopt
+opt_dff -keepdc
select -assert-count 1 t:$dffsr
select -assert-count 1 t:$dffsr r:WIDTH=4 %i
select -assert-count 1 t:$dffsre
@@ -48,8 +51,9 @@ select -assert-count 1 t:$sr r:WIDTH=4 %i
design -load orig
simplemap
-equiv_opt -undef -assert -multiclock opt_dff
-design -load postopt
+#equiv_opt -undef -assert -multiclock opt_dff
+#design -load postopt
+opt_dff
select -assert-count 1 t:$_DFF_PP0_
select -assert-count 1 t:$_DFF_PP1_
select -assert-count 1 t:$_DFFE_PN0P_
@@ -61,8 +65,9 @@ select -assert-none t:$_DFF_PP0_ t:$_DFF_PP1_ t:$_DFFE_PN0P_ t:$_DFFE_PN1P_ t:$_
design -load orig
simplemap
-equiv_opt -undef -assert -multiclock opt_dff -keepdc
-design -load postopt
+#equiv_opt -undef -assert -multiclock opt_dff -keepdc
+#design -load postopt
+opt_dff -keepdc
select -assert-count 1 t:$_DFF_PP0_
select -assert-count 1 t:$_DFF_PP1_
select -assert-count 2 t:$_DFFSR_PPP_
diff --git a/tests/opt/opt_expr_constconn.v b/tests/opt/opt_expr_constconn.v
new file mode 100644
index 000000000..d18b120e3
--- /dev/null
+++ b/tests/opt/opt_expr_constconn.v
@@ -0,0 +1,8 @@
+module top(...);
+
+input [7:0] A;
+output [7:0] B;
+wire [7:0] C = 3;
+assign B = A + C;
+
+endmodule
diff --git a/tests/opt/opt_expr_constconn.ys b/tests/opt/opt_expr_constconn.ys
new file mode 100644
index 000000000..9dd848a4b
--- /dev/null
+++ b/tests/opt/opt_expr_constconn.ys
@@ -0,0 +1,7 @@
+read_verilog opt_expr_constconn.v
+select -assert-count 1 t:$add
+select -assert-count 1 t:$add %ci w:C %i
+equiv_opt -assert opt_expr
+design -load postopt
+select -assert-count 1 t:$add
+select -assert-count 0 t:$add %ci w:C %i
diff --git a/tests/opt/opt_mem_feedback.ys b/tests/opt/opt_mem_feedback.ys
new file mode 100644
index 000000000..06d6e7e77
--- /dev/null
+++ b/tests/opt/opt_mem_feedback.ys
@@ -0,0 +1,189 @@
+# Good case: proper feedback port.
+
+read_verilog << EOT
+
+module top(...);
+
+input clk;
+input en;
+input s;
+
+input [3:0] ra;
+output [15:0] rd;
+input [3:0] wa;
+input [15:0] wd;
+
+reg [15:0] mem[0:15];
+
+assign rd = mem[ra];
+
+always @(posedge clk) begin
+ if (en) begin
+ mem[wa] <= {mem[wa][15:8], s ? wd[7:0] : mem[wa][7:0]};
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_clean
+
+design -save start
+memory_map
+design -save preopt
+
+design -load start
+opt_mem_feedback
+select -assert-count 1 t:$memrd_v2
+memory_map
+design -save postopt
+
+equiv_opt -assert -run prepare: :
+
+
+
+design -reset
+
+# Bad case: read port also used for other things.
+
+read_verilog << EOT
+
+module top(...);
+
+input clk;
+input en;
+input s;
+
+output [15:0] rd;
+input [3:0] wa;
+input [15:0] wd;
+
+reg [15:0] mem[0:15];
+
+assign rd = mem[wa];
+
+always @(posedge clk) begin
+ if (en) begin
+ mem[wa] <= {s ? rd : wd[15:8], s ? wd[7:0] : rd};
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_clean
+
+design -save start
+memory_map
+design -save preopt
+
+design -load start
+select -assert-count 1 t:$memrd
+opt_mem_feedback
+select -assert-count 1 t:$memrd
+memory_map
+design -save postopt
+
+equiv_opt -assert -run prepare: :
+
+
+
+design -reset
+
+# Bad case: another user of the mux out.
+
+read_verilog << EOT
+
+module top(...);
+
+input clk;
+input en;
+input s;
+
+output [15:0] rd;
+input [3:0] wa;
+input [15:0] wd;
+
+reg [15:0] mem[0:15];
+
+assign rd = s ? wd : mem[wa];
+
+always @(posedge clk) begin
+ if (en) begin
+ mem[wa] <= rd;
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_clean
+
+design -save start
+memory_map
+design -save preopt
+
+design -load start
+select -assert-count 1 t:$memrd
+opt_mem_feedback
+select -assert-count 1 t:$memrd
+memory_map
+design -save postopt
+
+equiv_opt -assert -run prepare: :
+
+
+
+design -reset
+
+# Tricky case: legit feedback path, but priority needs to be preserved.
+
+read_verilog << EOT
+
+module top(...);
+
+input clk;
+input sel;
+input [3:0] wa1;
+input [3:0] wa2;
+input [15:0] wd1;
+input [3:0] ra;
+output [15:0] rd;
+
+reg [15:0] mem [0:15];
+
+always @(posedge clk) begin
+ mem[wa1] <= sel ? wd1 : mem[wa1];
+ mem[wa2] <= mem[wa2];
+end
+
+assign rd = mem[ra];
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt_clean
+
+design -save start
+memory_map
+design -save preopt
+
+design -load start
+opt_mem_feedback
+select -assert-count 1 t:$memrd_v2
+memory_map
+design -save postopt
+
+equiv_opt -assert -run prepare: :
diff --git a/tests/opt/opt_mem_priority.ys b/tests/opt/opt_mem_priority.ys
new file mode 100644
index 000000000..a4119e12a
--- /dev/null
+++ b/tests/opt/opt_mem_priority.ys
@@ -0,0 +1,209 @@
+# Bad case: independent write ports.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] wa1, wa2, ra, wd1, wd2,
+ input clk, we1, we2,
+ output [3:0] rd);
+
+reg [3:0] mem[0:15];
+assign rd = mem[ra];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2)
+ mem[wa2] <= wd2;
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt
+memory -nomap
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:WR_PRIORITY_MASK=4'b0100 %i
+
+
+design -reset
+
+# Good case: write ports with definitely different addresses.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] wa, ra, wd1, wd2,
+ input clk, we1, we2,
+ output [3:0] rd);
+
+reg [3:0] mem[0:15];
+assign rd = mem[ra];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa] <= wd1;
+ if (we2)
+ mem[wa ^ 1] <= wd2;
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt
+memory -nomap
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:WR_PRIORITY_MASK=4'b0000 %i
+
+
+design -reset
+
+# Bad case 2: the above, but broken.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] wa, ra, wd1, wd2,
+ input clk, we1, we2,
+ output [3:0] rd);
+
+reg [3:0] mem[0:15];
+assign rd = mem[ra];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa] <= wd1;
+ if (we2)
+ mem[wa | 1] <= wd2;
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt
+memory -nomap
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:WR_PRIORITY_MASK=4'b0100 %i
+
+
+design -reset
+
+# Good case 2: write ports with disjoint bit enables.
+
+read_verilog << EOT
+
+module top(
+ input [3:0] wa1, wa2, ra,
+ input [1:0] wd1, wd2,
+ input clk, we1, we2,
+ output [3:0] rd);
+
+reg [3:0] mem[0:15];
+assign rd = mem[ra];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1][1:0] <= wd1;
+ if (we2)
+ mem[wa2][3:2] <= wd2;
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt
+memory -nomap
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:WR_PRIORITY_MASK=4'b0000 %i
+
+
+design -reset
+
+# Good case 3: write ports with soft priority logic already
+
+read_verilog << EOT
+
+module top(
+ input [3:0] wa1, wa2, ra, wd1, wd2,
+ input clk, we1, we2,
+ output [3:0] rd);
+
+reg [3:0] mem[0:15];
+assign rd = mem[ra];
+
+always @(posedge clk) begin
+ if (we1)
+ mem[wa1] <= wd1;
+ if (we2 && wa1 != wa2)
+ mem[wa2] <= wd2;
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt
+memory -nomap
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:WR_PRIORITY_MASK=4'b0000 %i
+
+
+design -reset
+
+# Good case 4: two wide write ports
+
+read_verilog << EOT
+
+module top(
+ input [5:0] wa1, wa2,
+ input [7:0] ra,
+ input [31:0] wd1, wd2,
+ input clk, we1, we2,
+ output [7:0] rd);
+
+reg [7:0] mem[0:255];
+assign rd = mem[ra];
+
+always @(posedge clk) begin
+ if (we1) begin
+ mem[{wa1, 2'b00}] <= wd1[7:0];
+ mem[{wa1, 2'b01}] <= wd1[15:8];
+ mem[{wa1, 2'b10}] <= wd1[23:16];
+ mem[{wa1, 2'b11}] <= wd1[31:24];
+ end
+ if (we2) begin
+ mem[{wa2, 2'b00}] <= wd2[7:0];
+ mem[{wa2, 2'b01}] <= wd2[15:8];
+ mem[{wa2, 2'b10}] <= wd2[23:16];
+ mem[{wa2, 2'b11}] <= wd2[31:24];
+ end
+end
+
+endmodule
+
+EOT
+
+hierarchy -auto-top
+proc
+opt
+opt_mem_priority
+memory_collect
+select -assert-count 1 t:$mem_v2
+select -assert-count 1 t:$mem_v2 r:WR_PRIORITY_MASK=64'h0804020100000000 %i
+memory_share
+select -assert-count 1 t:$mem_v2 r:WR_PRIORITY_MASK=64'h0f0f0f0f00000000 %i
+select -assert-count 1 t:$mem_v2 r:WR_WIDE_CONTINUATION=8'hee %i
diff --git a/tests/opt/opt_merge_init.ys b/tests/opt/opt_merge_init.ys
index 0176f09c7..20b6cabee 100644
--- a/tests/opt/opt_merge_init.ys
+++ b/tests/opt/opt_merge_init.ys
@@ -48,7 +48,7 @@ EOT
opt_merge
select -assert-count 1 t:$dff
-select -assert-count 1 a:init=2'bx1
+select -assert-count 1 a:init=2'bx1 a:init=2'b1x
design -reset
diff --git a/tests/opt/opt_reduce_bmux.ys b/tests/opt/opt_reduce_bmux.ys
new file mode 100644
index 000000000..55e0b6d4b
--- /dev/null
+++ b/tests/opt/opt_reduce_bmux.ys
@@ -0,0 +1,117 @@
+read_ilang << EOT
+
+module \top
+ wire width 12 input 0 \A
+ wire width 2 input 1 \S
+ wire width 6 output 2 \Y
+
+ cell $bmux $0
+ parameter \WIDTH 6
+ parameter \S_WIDTH 2
+ connect \A { \A [11:10] \A [3:2] \A [10:9] \A [7] \A [7] \A [8] \A [2] \A [7:6] \A [5] \A [5] \A [3:2] \A [5:4] \A [1] \A [1] \A [3:0] }
+ connect \S \S
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 1 t:$bmux r:WIDTH=4 %i
+
+design -reset
+
+read_ilang << EOT
+
+module \top
+ wire width 6 input 0 \A
+ wire width 2 input 1 \S
+ wire width 6 output 2 \Y
+
+ cell $bmux $0
+ parameter \WIDTH 6
+ parameter \S_WIDTH 2
+ connect \A { \A [5:0] \A [5:0] \A [5:0] \A [5:0] }
+ connect \S \S
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 0 t:$bmux
+
+design -reset
+
+read_ilang << EOT
+
+module \top
+ wire width 160 input 0 \A
+ wire width 2 input 1 \S
+ wire width 5 output 2 \Y
+
+ cell $bmux $0
+ parameter \WIDTH 5
+ parameter \S_WIDTH 5
+ connect \A \A
+ connect \S { \S [1] 1'1 \S [0] \S [1] 1'0 }
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 1 t:$bmux r:S_WIDTH=2 %i
+
+design -reset
+
+read_ilang << EOT
+
+module \top
+ wire width 10 input 0 \A
+ wire input 1 \S
+ wire width 5 output 2 \Y
+
+ cell $bmux $0
+ parameter \WIDTH 5
+ parameter \S_WIDTH 1
+ connect \A \A
+ connect \S \S
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 0 t:$bmux
+select -assert-count 1 t:$mux
+
+design -reset
+
+read_ilang << EOT
+
+module \top
+ wire width 5 input 0 \A
+ wire width 5 output 1 \Y
+
+ cell $bmux $0
+ parameter \WIDTH 5
+ parameter \S_WIDTH 0
+ connect \A \A
+ connect \S { }
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 0 t:$bmux
diff --git a/tests/opt/opt_reduce_demux.ys b/tests/opt/opt_reduce_demux.ys
new file mode 100644
index 000000000..3c5bd7d43
--- /dev/null
+++ b/tests/opt/opt_reduce_demux.ys
@@ -0,0 +1,91 @@
+read_ilang << EOT
+
+module \top
+ wire width 4 input 0 \A
+ wire width 2 input 1 \S
+ wire width 24 output 2 \Y
+
+ cell $demux $0
+ parameter \WIDTH 6
+ parameter \S_WIDTH 2
+ connect \A { \A [3] \A [1] 1'0 \A [2:0] }
+ connect \S \S
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 1 t:$demux r:WIDTH=4 %i
+
+design -reset
+
+read_ilang << EOT
+
+module \top
+ wire width 2 input 1 \S
+ wire width 24 output 2 \Y
+
+ cell $demux $0
+ parameter \WIDTH 6
+ parameter \S_WIDTH 2
+ connect \A 6'000000
+ connect \S \S
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 0 t:$demux
+
+design -reset
+
+read_ilang << EOT
+
+module \top
+ wire width 5 input 0 \A
+ wire width 2 input 1 \S
+ wire width 160 output 2 \Y
+
+ cell $demux $0
+ parameter \WIDTH 5
+ parameter \S_WIDTH 5
+ connect \A \A
+ connect \S { \S [0] \S [1] 1'1 \S [0] 1'0 }
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 1 t:$demux r:S_WIDTH=2 %i
+
+design -reset
+
+read_ilang << EOT
+
+module \top
+ wire width 5 input 0 \A
+ wire width 20 output 2 \Y
+
+ cell $demux $0
+ parameter \WIDTH 5
+ parameter \S_WIDTH 2
+ connect \A \A
+ connect \S { 2'10 }
+ connect \Y \Y
+ end
+end
+
+EOT
+
+equiv_opt -assert opt_reduce -fine
+opt_reduce -fine
+select -assert-count 0 t:$demux
diff --git a/tests/proc/bug2619.ys b/tests/proc/bug2619.ys
new file mode 100644
index 000000000..a080b94f5
--- /dev/null
+++ b/tests/proc/bug2619.ys
@@ -0,0 +1,23 @@
+read_verilog << EOT
+
+module top(...);
+
+input D1, D2, R, CLK;
+output reg Q1, Q2;
+
+always @(posedge CLK, posedge R) begin
+ Q1 <= 0;
+ if (!R) begin
+ Q1 <= D1;
+ Q2 <= D2;
+ end
+end
+
+endmodule
+
+EOT
+
+proc
+opt
+select -assert-count 1 t:$adff
+select -assert-count 1 t:$dffe
diff --git a/tests/proc/bug2656.ys b/tests/proc/bug2656.ys
new file mode 100644
index 000000000..3fe7cb33b
--- /dev/null
+++ b/tests/proc/bug2656.ys
@@ -0,0 +1,31 @@
+read_verilog <<EOT
+module top (...);
+
+input clk, rst, d1, d2;
+output q1, q2;
+
+always @(posedge clk)
+ if (clk)
+ q1 <= d1;
+
+always @(posedge clk, posedge rst)
+ if (rst)
+ q2 <= 0;
+ else if (clk)
+ q2 <= d2;
+
+endmodule
+EOT
+
+proc
+opt
+
+select -assert-count 1 t:$dff
+select -assert-count 1 w:clk %a %co t:$dff %i
+select -assert-count 1 w:d1 %a %co t:$dff %i
+select -assert-count 1 w:q1 %a %ci t:$dff %i
+select -assert-count 1 t:$adff
+select -assert-count 1 w:clk %a %co t:$adff %i
+select -assert-count 1 w:rst %a %co t:$adff %i
+select -assert-count 1 w:d2 %a %co t:$adff %i
+select -assert-count 1 w:q2 %a %ci t:$adff %i
diff --git a/tests/proc/bug2962.ys b/tests/proc/bug2962.ys
new file mode 100644
index 000000000..99da8db5d
--- /dev/null
+++ b/tests/proc/bug2962.ys
@@ -0,0 +1,22 @@
+read_ilang << EOT
+module \top
+ wire width 4 input 1 \a
+ wire width 2 input 2 \b
+ wire input 3 \clk
+ wire width 4 output 4 \q
+ wire input 5 \en
+ wire width 4 \nq
+ process \p
+ assign \nq \a
+ assign \nq [1:0] \b
+ switch \en
+ case 1'1
+ assign \nq [3] 1'0
+ end
+ sync posedge \clk
+ update \q \nq
+ end
+end
+EOT
+proc
+check -assert
diff --git a/tests/proc/rmdead.v b/tests/proc/rmdead.v
new file mode 100644
index 000000000..2be89e533
--- /dev/null
+++ b/tests/proc/rmdead.v
@@ -0,0 +1,46 @@
+module top (
+ input wire signed x,
+ output reg [31:0] y
+);
+ wire signed fail = ~x;
+
+ always @*
+ case (x)
+ 1'b0: y = 0;
+ 1'b1: y = 1;
+ default: y = fail;
+ endcase
+
+ always @*
+ case (x)
+ 2'sb00: y = 0;
+ 2'sb00: y = fail;
+ endcase
+
+ always @*
+ case (x)
+ 2'sb00: y = 0;
+ default: y = fail;
+ 2'sb01: y = 1;
+ 2'sb10: y = 2;
+ 2'sb11: y = 3;
+ 2'sb00: y = fail;
+ 2'sb01: y = fail;
+ 2'sb10: y = fail;
+ 2'sb11: y = fail;
+ endcase
+
+
+ always @*
+ case ({x, x})
+ 2'b00: y = 0;
+ 2'b01: y = 1;
+ 2'b10: y = 2;
+ 2'b11: y = 3;
+ default: y = fail;
+ 2'b00: y = fail;
+ 2'b01: y = fail;
+ 2'b10: y = fail;
+ 2'b11: y = fail;
+ endcase
+endmodule
diff --git a/tests/proc/rmdead.ys b/tests/proc/rmdead.ys
new file mode 100644
index 000000000..697d899e3
--- /dev/null
+++ b/tests/proc/rmdead.ys
@@ -0,0 +1,4 @@
+read_verilog rmdead.v
+proc
+opt_clean
+select -assert-count 0 w:fail
diff --git a/tests/sat/.gitignore b/tests/sat/.gitignore
index 8355de9dc..664425d73 100644
--- a/tests/sat/.gitignore
+++ b/tests/sat/.gitignore
@@ -1,2 +1,4 @@
*.log
run-test.mk
+*.vcd
+*.fst
diff --git a/tests/sat/alu.v b/tests/sat/alu.v
new file mode 100644
index 000000000..9826fe05d
--- /dev/null
+++ b/tests/sat/alu.v
@@ -0,0 +1,79 @@
+module alu(
+ input clk,
+ input [7:0] A,
+ input [7:0] B,
+ input [3:0] operation,
+ output reg [7:0] result,
+ output reg CF,
+ output reg ZF,
+ output reg SF
+);
+
+ localparam ALU_OP_ADD /* verilator public_flat */ = 4'b0000;
+ localparam ALU_OP_SUB /* verilator public_flat */ = 4'b0001;
+ localparam ALU_OP_ADC /* verilator public_flat */ = 4'b0010;
+ localparam ALU_OP_SBC /* verilator public_flat */ = 4'b0011;
+
+ localparam ALU_OP_AND /* verilator public_flat */ = 4'b0100;
+ localparam ALU_OP_OR /* verilator public_flat */ = 4'b0101;
+ localparam ALU_OP_NOT /* verilator public_flat */ = 4'b0110;
+ localparam ALU_OP_XOR /* verilator public_flat */ = 4'b0111;
+
+ localparam ALU_OP_SHL /* verilator public_flat */ = 4'b1000;
+ localparam ALU_OP_SHR /* verilator public_flat */ = 4'b1001;
+ localparam ALU_OP_SAL /* verilator public_flat */ = 4'b1010;
+ localparam ALU_OP_SAR /* verilator public_flat */ = 4'b1011;
+
+ localparam ALU_OP_ROL /* verilator public_flat */ = 4'b1100;
+ localparam ALU_OP_ROR /* verilator public_flat */ = 4'b1101;
+ localparam ALU_OP_RCL /* verilator public_flat */ = 4'b1110;
+ localparam ALU_OP_RCR /* verilator public_flat */ = 4'b1111;
+
+ reg [8:0] tmp;
+
+ always @(posedge clk)
+ begin
+ case (operation)
+ ALU_OP_ADD :
+ tmp = A + B;
+ ALU_OP_SUB :
+ tmp = A - B;
+ ALU_OP_ADC :
+ tmp = A + B + { 7'b0000000, CF };
+ ALU_OP_SBC :
+ tmp = A - B - { 7'b0000000, CF };
+ ALU_OP_AND :
+ tmp = {1'b0, A & B };
+ ALU_OP_OR :
+ tmp = {1'b0, A | B };
+ ALU_OP_NOT :
+ tmp = {1'b0, ~B };
+ ALU_OP_XOR :
+ tmp = {1'b0, A ^ B};
+ ALU_OP_SHL :
+ tmp = { A[7], A[6:0], 1'b0};
+ ALU_OP_SHR :
+ tmp = { A[0], 1'b0, A[7:1]};
+ ALU_OP_SAL :
+ // Same as SHL
+ tmp = { A[7], A[6:0], 1'b0};
+ ALU_OP_SAR :
+ tmp = { A[0], A[7], A[7:1]};
+ ALU_OP_ROL :
+ tmp = { A[7], A[6:0], A[7]};
+ ALU_OP_ROR :
+ tmp = { A[0], A[0], A[7:1]};
+ ALU_OP_RCL :
+ tmp = { A[7], A[6:0], CF};
+ ALU_OP_RCR :
+ tmp = { A[0], CF, A[7:1]};
+ endcase
+
+ CF <= tmp[8];
+ ZF <= tmp[7:0] == 0;
+ SF <= tmp[7];
+
+ result <= tmp[7:0];
+ end
+endmodule
+
diff --git a/tests/sat/grom.ys b/tests/sat/grom.ys
new file mode 100644
index 000000000..da0f3b620
--- /dev/null
+++ b/tests/sat/grom.ys
@@ -0,0 +1,9 @@
+read_verilog grom_computer.v grom_cpu.v alu.v ram_memory.v;
+prep -top grom_computer;
+sim -clock clk -reset reset -fst grom.fst -vcd grom.vcd -n 80
+
+sim -clock clk -r grom.fst -scope grom_computer -start 25ns -stop 100ns -sim-cmp
+
+sim -clock clk -r grom.fst -scope grom_computer -stop 100ns -sim-gold
+
+sim -clock clk -r grom.fst -scope grom_computer -n 10 -sim-gate
diff --git a/tests/sat/grom_computer.v b/tests/sat/grom_computer.v
new file mode 100644
index 000000000..63a5c8ff8
--- /dev/null
+++ b/tests/sat/grom_computer.v
@@ -0,0 +1,31 @@
+module grom_computer
+ (input clk, // Main Clock
+ input reset, // reset
+ output hlt,
+ output reg[7:0] display_out
+ );
+
+ wire [11:0] addr;
+ wire [7:0] memory_out;
+ wire [7:0] memory_in;
+ wire mem_enable;
+ wire we;
+ wire ioreq;
+
+ grom_cpu cpu(.clk(clk),.reset(reset),.addr(addr),.data_in(memory_out),.data_out(memory_in),.we(we),.ioreq(ioreq),.hlt(hlt));
+
+ assign mem_enable = we & ~ioreq;
+
+ ram_memory memory(.clk(clk),.addr(addr),.data_in(memory_in),.we(mem_enable),.data_out(memory_out));
+
+ always @(posedge clk)
+ begin
+ if(ioreq==1 && we==1)
+ begin
+ display_out <= memory_in;
+ `ifdef DISASSEMBLY
+ $display("Display output : %h", memory_in);
+ `endif
+ end
+ end
+endmodule
diff --git a/tests/sat/grom_cpu.v b/tests/sat/grom_cpu.v
new file mode 100644
index 000000000..f9fef043b
--- /dev/null
+++ b/tests/sat/grom_cpu.v
@@ -0,0 +1,747 @@
+module grom_cpu(
+ input clk,
+ input reset,
+ output reg [11:0] addr,
+ input [7:0] data_in,
+ output reg [7:0] data_out,
+ output reg we,
+ output reg ioreq,
+ output reg hlt
+);
+
+ reg[11:0] PC /* verilator public_flat */; // Program counter
+ reg[7:0] IR /* verilator public_flat */; // Instruction register
+ reg[7:0] VALUE /* verilator public_flat */; // Temp reg for storing 2nd operand
+ reg[3:0] CS /* verilator public_flat */; // Code segment regiser
+ reg[3:0] DS /* verilator public_flat */; // Data segment regiser
+ reg[11:0] SP /* verilator public_flat */; // Stack pointer regiser
+ reg[7:0] R[0:3] /* verilator public_flat */; // General purpose registers
+ reg[11:0] FUTURE_PC /* verilator public_flat */; // PC to jump to
+
+ localparam STATE_RESET /*verilator public_flat*/ = 5'b00000;
+ localparam STATE_FETCH_PREP /*verilator public_flat*/ = 5'b00001;
+ localparam STATE_FETCH_WAIT /*verilator public_flat*/ = 5'b00010;
+ localparam STATE_FETCH /*verilator public_flat*/ = 5'b00011;
+ localparam STATE_EXECUTE /*verilator public_flat*/ = 5'b00100;
+ localparam STATE_FETCH_VALUE_PREP /*verilator public_flat*/ = 5'b00101;
+ localparam STATE_FETCH_VALUE /*verilator public_flat*/ = 5'b00110;
+ localparam STATE_EXECUTE_DBL /*verilator public_flat*/ = 5'b00111;
+ localparam STATE_LOAD_VALUE /*verilator public_flat*/ = 5'b01000;
+ localparam STATE_LOAD_VALUE_WAIT /*verilator public_flat*/ = 5'b01001;
+ localparam STATE_ALU_RESULT_WAIT /*verilator public_flat*/ = 5'b01010;
+ localparam STATE_ALU_RESULT /*verilator public_flat*/ = 5'b01011;
+ localparam STATE_PUSH_PC_LOW /*verilator public_flat*/ = 5'b01100;
+ localparam STATE_JUMP /*verilator public_flat*/ = 5'b01101;
+ localparam STATE_RET_VALUE_WAIT /*verilator public_flat*/ = 5'b01110;
+ localparam STATE_RET_VALUE /*verilator public_flat*/ = 5'b01111;
+ localparam STATE_RET_VALUE_WAIT2 /*verilator public_flat*/ = 5'b10000;
+ localparam STATE_RET_VALUE2 /*verilator public_flat*/ = 5'b10001;
+
+ reg [4:0] state /* verilator public_flat */ = STATE_RESET;
+
+ reg [7:0] alu_a /* verilator public_flat */;
+ reg [7:0] alu_b /* verilator public_flat */;
+ reg [3:0] alu_op /* verilator public_flat */;
+
+ reg [1:0] RESULT_REG /* verilator public_flat */;
+
+ wire [7:0] alu_res /* verilator public_flat */;
+ wire alu_CF /* verilator public_flat */;
+ wire alu_ZF /* verilator public_flat */;
+ wire alu_SF /* verilator public_flat */;
+ reg jump;
+
+ alu alu(.clk(clk),.A(alu_a),.B(alu_b),.operation(alu_op),.result(alu_res),.CF(alu_CF),.ZF(alu_ZF),.SF(alu_SF));
+
+ always @(posedge clk)
+ begin
+ if (reset)
+ begin
+ state <= STATE_RESET;
+ hlt <= 0;
+ end
+ else
+ begin
+ case (state)
+ STATE_RESET :
+ begin
+ PC <= 12'h000;
+ state <= STATE_FETCH_PREP;
+ CS <= 4'h0;
+ DS <= 4'h0;
+ R[0] <= 8'h00;
+ R[1] <= 8'h00;
+ R[2] <= 8'h00;
+ R[3] <= 8'h00;
+ SP <= 12'hfff;
+ end
+
+ STATE_FETCH_PREP :
+ begin
+ addr <= PC;
+ we <= 0;
+ ioreq <= 0;
+
+ state <= STATE_FETCH_WAIT;
+ end
+
+ STATE_FETCH_WAIT :
+ begin
+ // Sync with memory due to CLK
+ state <= (hlt) ? STATE_FETCH_PREP : STATE_FETCH;
+ end
+
+ STATE_FETCH :
+ begin
+ IR <= data_in;
+ PC <= PC + 1;
+
+ state <= STATE_EXECUTE;
+ end
+ STATE_EXECUTE :
+ begin
+ `ifdef DISASSEMBLY
+ $display(" PC %h R0 %h R1 %h R2 %h R3 %h CS %h DS %h SP %h ALU [%d %d %d]", PC, R[0], R[1], R[2], R[3], CS, DS, SP, alu_CF,alu_SF,alu_ZF);
+ `endif
+ if (IR[7])
+ begin
+ addr <= PC;
+ state <= STATE_FETCH_VALUE_PREP;
+ PC <= PC + 1;
+ end
+ else
+ begin
+ case(IR[6:4])
+ 3'b000 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("MOV R%d,R%d",IR[3:2],IR[1:0]);
+ `endif
+ R[IR[3:2]] <= R[IR[1:0]];
+ state <= STATE_FETCH_PREP;
+ end
+ 3'b001 :
+ begin
+ alu_a <= R[0]; // first input R0
+ alu_b <= R[IR[1:0]];
+ RESULT_REG <= 0; // result in R0
+ alu_op <= { 2'b00, IR[3:2] };
+
+ state <= STATE_ALU_RESULT_WAIT;
+
+ `ifdef DISASSEMBLY
+ case(IR[3:2])
+ 2'b00 : begin
+ $display("ADD R%d",IR[1:0]);
+ end
+ 2'b01 : begin
+ $display("SUB R%d",IR[1:0]);
+ end
+ 2'b10 : begin
+ $display("ADC R%d",IR[1:0]);
+ end
+ 2'b11 : begin
+ $display("SBC R%d",IR[1:0]);
+ end
+ endcase
+ `endif
+ end
+ 3'b010 :
+ begin
+ alu_a <= R[0]; // first input R0
+ alu_b <= R[IR[1:0]];
+ RESULT_REG <= 0; // result in R0
+ alu_op <= { 2'b01, IR[3:2] };
+ state <= STATE_ALU_RESULT_WAIT;
+ `ifdef DISASSEMBLY
+ case(IR[3:2])
+ 2'b00 : begin
+ $display("AND R%d",IR[1:0]);
+ end
+ 2'b01 : begin
+ $display("OR R%d",IR[1:0]);
+ end
+ 2'b10 : begin
+ $display("NOT R%d",IR[1:0]);
+ end
+ 2'b11 : begin
+ $display("XOR R%d",IR[1:0]);
+ end
+ endcase
+ `endif
+ end
+ 3'b011 :
+ begin
+ RESULT_REG <= IR[1:0]; // result in REG
+ // CMP and TEST are not storing result
+ state <= IR[3] ? STATE_FETCH_PREP : STATE_ALU_RESULT_WAIT;
+ // CMP and TEST are having first input R0, for INC and DEC is REG
+ alu_a <= IR[3] ? R[0] : R[IR[1:0]];
+ // CMP and TEST are having second input REG, for INC and DEC is 1
+ alu_b <= IR[3] ? R[IR[1:0]] : 8'b00000001;
+
+ case(IR[3:2])
+ 2'b00 : begin
+ `ifdef DISASSEMBLY
+ $display("INC R%d",IR[1:0]);
+ `endif
+ alu_op <= 4'b0001; // ALU_OP_ADD
+ end
+ 2'b01 : begin
+ `ifdef DISASSEMBLY
+ $display("DEC R%d",IR[1:0]);
+ `endif
+ alu_op <= 4'b0001; // ALU_OP_SUB
+ end
+ 2'b10 : begin
+ `ifdef DISASSEMBLY
+ $display("CMP R%d",IR[1:0]);
+ `endif
+ alu_op <= 4'b0001; // ALU_OP_SUB
+ end
+ 2'b11 : begin
+ `ifdef DISASSEMBLY
+ $display("TST R%d",IR[1:0]);
+ `endif
+ alu_op <= 4'b0100; // ALU_OP_AND
+ end
+ endcase
+ end
+ 3'b100 :
+ begin
+ if (IR[3]==0)
+ begin
+ alu_a <= R[0]; // first input R0
+ // no 2nd input
+ RESULT_REG <= 0; // result in R0
+ alu_op <= { 1'b1, IR[2:0] };
+ `ifdef DISASSEMBLY
+ case(IR[2:0])
+ 3'b000 : begin
+ $display("SHL");
+ end
+ 3'b001 : begin
+ $display("SHR");
+ end
+ 3'b010 : begin
+ $display("SAL");
+ end
+ 3'b011 : begin
+ $display("SAR");
+ end
+ 3'b100 : begin
+ $display("ROL");
+ end
+ 3'b101 : begin
+ $display("ROR");
+ end
+ 3'b110 : begin
+ $display("RCL");
+ end
+ 3'b111 : begin
+ $display("RCR");
+ end
+ endcase
+ `endif
+ state <= STATE_ALU_RESULT_WAIT;
+ end
+ else
+ begin
+ if (IR[2]==0)
+ begin
+ `ifdef DISASSEMBLY
+ $display("PUSH R%d",IR[1:0]);
+ `endif
+ addr <= SP;
+ we <= 1;
+ ioreq <= 0;
+ data_out <= R[IR[1:0]];
+ SP <= SP - 1;
+ state <= STATE_FETCH_PREP;
+ end
+ else
+ begin
+ `ifdef DISASSEMBLY
+ $display("POP R%d",IR[1:0]);
+ `endif
+ addr <= SP + 1;
+ we <= 0;
+ ioreq <= 0;
+ RESULT_REG <= IR[1:0];
+ SP <= SP + 1;
+ state <= STATE_LOAD_VALUE_WAIT;
+ end
+ end
+ end
+ 3'b101 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("LOAD R%d,[R%d]", IR[3:2], IR[1:0]);
+ `endif
+ addr <= { DS, R[IR[1:0]] };
+ we <= 0;
+ ioreq <= 0;
+ RESULT_REG <= IR[3:2];
+
+ state <= STATE_LOAD_VALUE_WAIT;
+ end
+ 3'b110 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("STORE [R%d],R%d", IR[3:2], IR[1:0]);
+ `endif
+ addr <= { DS, R[IR[3:2]] };
+ we <= 1;
+ ioreq <= 0;
+ data_out <= R[IR[1:0]];
+
+ state <= STATE_FETCH_PREP;
+ end
+ 3'b111 :
+ begin
+ // Special instuctions
+ case(IR[3:2])
+ 2'b00 : begin
+ CS <= R[IR[1:0]][3:0];
+ state <= STATE_FETCH_PREP;
+ `ifdef DISASSEMBLY
+ $display("MOV CS,R%d",IR[1:0]);
+ `endif
+ end
+ 2'b01 : begin
+ DS <= R[IR[1:0]][3:0];
+ state <= STATE_FETCH_PREP;
+ `ifdef DISASSEMBLY
+ $display("MOV DS,R%d",IR[1:0]);
+ `endif
+ end
+ 2'b10 : begin
+ case(IR[1:0])
+ 2'b00 : begin
+ `ifdef DISASSEMBLY
+ $display("PUSH CS");
+ `endif
+ addr <= SP;
+ we <= 1;
+ ioreq <= 0;
+ data_out <= { 4'b0000, CS};
+ SP <= SP - 1;
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b01 : begin
+ `ifdef DISASSEMBLY
+ $display("PUSH DS");
+ `endif
+ addr <= SP;
+ we <= 1;
+ ioreq <= 0;
+ data_out <= { 4'b0000, DS};
+ SP <= SP - 1;
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b10 : begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode");
+ `endif
+ end
+ 2'b11 : begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode");
+ `endif
+ end
+ endcase
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b11 : begin
+ case(IR[1:0])
+ 2'b00 : begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode");
+ `endif
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b01 : begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode");
+ `endif
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b10 : begin
+ `ifdef DISASSEMBLY
+ $display("RET");
+ `endif
+ addr <= SP + 1;
+ we <= 0;
+ ioreq <= 0;
+ SP <= SP + 1;
+ state <= STATE_RET_VALUE_WAIT;
+ end
+ 2'b11 : begin
+ hlt <= 1;
+ `ifdef DISASSEMBLY
+ $display("HALT");
+ `endif
+ state <= STATE_FETCH_PREP;
+ end
+ endcase
+ end
+ endcase
+ end
+ endcase
+ end
+ end
+ STATE_FETCH_VALUE_PREP :
+ begin
+ // Sync with memory due to CLK
+ state <= STATE_FETCH_VALUE;
+ end
+ STATE_FETCH_VALUE :
+ begin
+ VALUE <= data_in;
+ state <= STATE_EXECUTE_DBL;
+ end
+ STATE_EXECUTE_DBL :
+ begin
+ case(IR[6:4])
+ 3'b000 :
+ begin
+ if (IR[3]==0)
+ begin
+ case(IR[2:0])
+ 3'b000 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JMP %h ",{ CS, VALUE[7:0] });
+ `endif
+ jump = 1;
+ end
+ 3'b001 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JC %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_CF==1);
+ end
+ 3'b010 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JNC %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_CF==0);
+ end
+ 3'b011 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JM %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_SF==1);
+ end
+ 3'b100 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JP %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_SF==0);
+ end
+ 3'b101 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JZ %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_ZF==1);
+ end
+ 3'b110 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JNZ %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_ZF==0);
+ end
+ 3'b111 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode %h",IR);
+ `endif
+ jump = 0;
+ end
+ endcase
+
+ if (jump)
+ begin
+ PC <= { CS, VALUE[7:0] };
+ addr <= { CS, VALUE[7:0] };
+ we <= 0;
+ ioreq <= 0;
+ end
+ state <= STATE_FETCH_PREP;
+ end
+ else
+ begin
+ case(IR[2:0])
+ 3'b000 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JR %h ", PC + {VALUE[7],VALUE[7],VALUE[7],VALUE[7],VALUE[7:0]} );
+ `endif
+ jump = 1;
+ end
+ 3'b001 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JRC %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_CF==1);
+ end
+ 3'b010 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JRNC %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_CF==0);
+ end
+ 3'b011 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JRM %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_SF==1);
+ end
+ 3'b100 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JRP %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_SF==0);
+ end
+ 3'b101 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JRZ %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_ZF==1);
+ end
+ 3'b110 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JRNZ %h ",{CS, VALUE[7:0] });
+ `endif
+ jump = (alu_ZF==0);
+ end
+ 3'b111 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode %h",IR);
+ `endif
+ jump = 0;
+ end
+ endcase
+ if (jump)
+ begin
+ PC <= PC + {VALUE[7],VALUE[7],VALUE[7],VALUE[7],VALUE[7:0]};
+ addr <= PC + {VALUE[7],VALUE[7],VALUE[7],VALUE[7],VALUE[7:0]};
+ we <= 0;
+ ioreq <= 0;
+ end
+ state <= STATE_FETCH_PREP;
+ end
+ end
+ 3'b001 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("JUMP %h ",{ IR[3:0], VALUE[7:0] });
+ `endif
+ PC <= { IR[3:0], VALUE[7:0] };
+ addr <= { IR[3:0], VALUE[7:0] };
+ we <= 0;
+ ioreq <= 0;
+ state <= STATE_FETCH_PREP;
+ end
+ 3'b010 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("CALL %h ",{ IR[3:0], VALUE[7:0] });
+ `endif
+ FUTURE_PC <= { IR[3:0], VALUE[7:0] };
+ addr <= SP;
+ we <= 1;
+ ioreq <= 0;
+ data_out <= { 4'b0000, PC[11:8]};
+ SP <= SP - 1;
+ state <= STATE_PUSH_PC_LOW;
+ end
+ 3'b011 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("MOV SP,%h ",{ IR[3:0], VALUE[7:0] });
+ `endif
+ SP <= { IR[3:0], VALUE[7:0] };
+ state <= STATE_FETCH_PREP;
+ end
+ 3'b100 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("IN R%d,[0x%h]",IR[1:0], VALUE);
+ `endif
+ ioreq <= 1;
+ we <= 0;
+ addr <= { 4'b0000, VALUE };
+ RESULT_REG <= IR[1:0];
+ state <= STATE_LOAD_VALUE_WAIT;
+ end
+ 3'b101 :
+ begin
+ `ifdef DISASSEMBLY
+ $display("OUT [0x%h],R%d",VALUE,IR[1:0]);
+ `endif
+ ioreq <= 1;
+ we <= 1;
+ addr <= { 4'b0000, VALUE };
+ data_out <= R[IR[1:0]];
+ state <= STATE_FETCH_PREP;
+ end
+ 3'b110 :
+ begin
+ // Special instuctions
+ case(IR[1:0])
+ 2'b00 : begin
+ `ifdef DISASSEMBLY
+ $display("MOV CS,0x%h",VALUE);
+ `endif
+ CS <= VALUE[3:0];
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b01 : begin
+ `ifdef DISASSEMBLY
+ $display("MOV DS,0x%h",VALUE);
+ `endif
+ DS <= VALUE[3:0];
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b10 : begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode %h",IR);
+ `endif
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b11 : begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode %h",IR);
+ `endif
+ state <= STATE_FETCH_PREP;
+ end
+ endcase
+ end
+ 3'b111 :
+ begin
+ case(IR[3:2])
+ 2'b00 : begin
+ `ifdef DISASSEMBLY
+ $display("MOV R%d,0x%h",IR[1:0],VALUE);
+ `endif
+ R[IR[1:0]] <= VALUE;
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b01 : begin
+ `ifdef DISASSEMBLY
+ $display("LOAD R%d,[0x%h]",IR[1:0], {DS, VALUE});
+ `endif
+ addr <= { DS, VALUE };
+ we <= 0;
+ ioreq <= 0;
+ RESULT_REG <= IR[1:0];
+
+ state <= STATE_LOAD_VALUE_WAIT;
+ end
+ 2'b10 : begin
+ `ifdef DISASSEMBLY
+ $display("STORE [0x%h],R%d", {DS, VALUE}, IR[1:0]);
+ `endif
+ addr <= { DS, VALUE };
+ we <= 1;
+ ioreq <= 0;
+ data_out <= R[IR[1:0]];
+
+ state <= STATE_FETCH_PREP;
+ end
+ 2'b11 : begin
+ `ifdef DISASSEMBLY
+ $display("Unused opcode %h",IR);
+ `endif
+ state <= STATE_FETCH_PREP;
+ end
+ endcase
+ end
+ endcase
+ end
+ STATE_LOAD_VALUE_WAIT :
+ begin
+ // Sync with memory due to CLK
+ state <= STATE_LOAD_VALUE;
+ end
+ STATE_LOAD_VALUE :
+ begin
+ R[RESULT_REG] <= data_in;
+ we <= 0;
+ state <= STATE_FETCH_PREP;
+ end
+ STATE_ALU_RESULT_WAIT :
+ begin
+ state <= STATE_ALU_RESULT;
+ end
+ STATE_ALU_RESULT :
+ begin
+ R[RESULT_REG] <= alu_res;
+ state <= STATE_FETCH_PREP;
+ end
+ STATE_PUSH_PC_LOW :
+ begin
+ addr <= SP;
+ we <= 1;
+ ioreq <= 0;
+ data_out <= PC[7:0];
+ SP <= SP - 1;
+ state <= STATE_JUMP;
+ end
+ STATE_JUMP :
+ begin
+ `ifdef DISASSEMBLY
+ $display("Jumping to %h",FUTURE_PC);
+ `endif
+ PC <= FUTURE_PC;
+ state <= STATE_FETCH_PREP;
+ end
+ STATE_RET_VALUE_WAIT :
+ begin
+ // Sync with memory due to CLK
+ state <= STATE_RET_VALUE;
+ end
+ STATE_RET_VALUE :
+ begin
+ FUTURE_PC <= { 4'b0000, data_in };
+ we <= 0;
+ state <= STATE_RET_VALUE_WAIT2;
+
+ addr <= SP + 1;
+ we <= 0;
+ ioreq <= 0;
+ SP <= SP + 1;
+ end
+ STATE_RET_VALUE_WAIT2 :
+ begin
+ // Sync with memory due to CLK
+ state <= STATE_RET_VALUE2;
+ end
+ STATE_RET_VALUE2 :
+ begin
+ FUTURE_PC <= FUTURE_PC | ({ 4'b0000, data_in } << 8);
+ we <= 0;
+ state <= STATE_JUMP;
+ end
+ default :
+ begin
+ state <= STATE_FETCH_PREP;
+ end
+ endcase
+ end
+ end
+endmodule
diff --git a/tests/sat/ram_memory.v b/tests/sat/ram_memory.v
new file mode 100644
index 000000000..053ef206c
--- /dev/null
+++ b/tests/sat/ram_memory.v
@@ -0,0 +1,37 @@
+module ram_memory(
+ input clk,
+ input [11:0] addr,
+ input [7:0] data_in,
+ input we,
+ output reg [7:0] data_out
+);
+
+ reg [7:0] store[0:4095] /* verilator public_flat */;
+
+ initial
+ begin
+ store[0] <= 8'b11100001; // MOV DS,2
+ store[1] <= 8'b00000010; //
+ store[2] <= 8'b01010100; // LOAD R1,[R0]
+ store[3] <= 8'b00110001; // INC R1
+ store[4] <= 8'b00110001; // INC R1
+ store[5] <= 8'b01100001; // STORE [R0],R1
+ store[6] <= 8'b11010001; // OUT [0],R1
+ store[7] <= 8'b00000000; //
+ store[8] <= 8'b00110001; // INC R1
+ store[9] <= 8'b10100001; // CALL 0x100
+ store[10] <= 8'b00000000; //
+ store[11] <= 8'b01111111; // HLT
+
+
+ store[256] <= 8'b11010001; // OUT [0],R1
+ store[257] <= 8'b00000000; //
+ store[258] <= 8'b01111110; // RET
+ end
+
+ always @(posedge clk)
+ if (we)
+ store[addr] <= data_in;
+ else
+ data_out <= store[addr];
+endmodule
diff --git a/tests/sat/sim_counter.ys b/tests/sat/sim_counter.ys
new file mode 100644
index 000000000..a0ff41b6e
--- /dev/null
+++ b/tests/sat/sim_counter.ys
@@ -0,0 +1,48 @@
+# Create stimulus file
+read_verilog <<EOT
+module top (clk, reset, cnt);
+
+input clk;
+input reset;
+output [7:0] cnt;
+
+reg [7:0] cnt;
+
+endmodule
+EOT
+prep -top top;
+sim -clock clk -reset reset -fst stimulus.fst -n 10
+design -reset
+
+# Counter implementation
+read_verilog <<EOT
+module top (clk, reset, cnt);
+
+input clk;
+input reset;
+output [7:0] cnt;
+
+reg [7:0] cnt;
+
+always @(posedge clk)
+ if (!reset)
+ cnt = cnt + 1;
+ else
+ cnt = 0;
+
+endmodule
+EOT
+prep -top top;
+
+# Simulate with stimulus
+sim -clock clk -scope top -r stimulus.fst
+
+# Stimulus does not have counter values
+# x in FST can match any value in simulation
+sim -clock clk -scope top -r stimulus.fst -sim-gate
+
+# Stimulus does not have counter values
+# x in simulation can match any value in FST
+# so we expect error
+logger -expect error "Signal difference" 1
+sim -clock clk -scope top -r stimulus.fst -sim-gold
diff --git a/tests/simple/asgn_binop.sv b/tests/simple/asgn_binop.sv
new file mode 100644
index 000000000..b134e5697
--- /dev/null
+++ b/tests/simple/asgn_binop.sv
@@ -0,0 +1,23 @@
+`define TEST(name, asgnop)\
+ module test_``name ( \
+ input logic [3:0] a, b, \
+ output logic [3:0] c \
+ ); \
+ always @* begin \
+ c = a; \
+ c asgnop b; \
+ end \
+ endmodule
+
+`TEST(add, +=)
+`TEST(sub, -=)
+`TEST(mul, *=)
+`TEST(div, /=)
+`TEST(mod, %=)
+`TEST(bit_and, &=)
+`TEST(bit_or , |=)
+`TEST(bit_xor, ^=)
+`TEST(shl, <<=)
+`TEST(shr, >>=)
+`TEST(sshl, <<<=)
+`TEST(sshr, >>>=)
diff --git a/tests/simple/attrib01_module.v b/tests/simple/attrib01_module.v
index adef34f5b..d6e36fb80 100644
--- a/tests/simple/attrib01_module.v
+++ b/tests/simple/attrib01_module.v
@@ -1,4 +1,4 @@
-module bar(clk, rst, inp, out);
+module attrib01_bar(clk, rst, inp, out);
input wire clk;
input wire rst;
input wire inp;
@@ -10,12 +10,12 @@ module bar(clk, rst, inp, out);
endmodule
-module foo(clk, rst, inp, out);
+module attrib01_foo(clk, rst, inp, out);
input wire clk;
input wire rst;
input wire inp;
output wire out;
- bar bar_instance (clk, rst, inp, out);
+ attrib01_bar bar_instance (clk, rst, inp, out);
endmodule
diff --git a/tests/simple/attrib02_port_decl.v b/tests/simple/attrib02_port_decl.v
index 3505e7265..989213b77 100644
--- a/tests/simple/attrib02_port_decl.v
+++ b/tests/simple/attrib02_port_decl.v
@@ -1,4 +1,4 @@
-module bar(clk, rst, inp, out);
+module attrib02_bar(clk, rst, inp, out);
(* this_is_clock = 1 *)
input wire clk;
(* this_is_reset = 1 *)
@@ -13,13 +13,13 @@ module bar(clk, rst, inp, out);
endmodule
-module foo(clk, rst, inp, out);
+module attrib02_foo(clk, rst, inp, out);
(* this_is_the_master_clock *)
input wire clk;
input wire rst;
input wire inp;
output wire out;
- bar bar_instance (clk, rst, inp, out);
+ attrib02_bar bar_instance (clk, rst, inp, out);
endmodule
diff --git a/tests/simple/attrib03_parameter.v b/tests/simple/attrib03_parameter.v
index 562d225cd..d2ae98978 100644
--- a/tests/simple/attrib03_parameter.v
+++ b/tests/simple/attrib03_parameter.v
@@ -1,4 +1,4 @@
-module bar(clk, rst, inp, out);
+module attrib03_bar(clk, rst, inp, out);
(* bus_width *)
parameter WIDTH = 2;
@@ -17,12 +17,12 @@ module bar(clk, rst, inp, out);
endmodule
-module foo(clk, rst, inp, out);
+module attrib03_foo(clk, rst, inp, out);
input wire clk;
input wire rst;
input wire [7:0] inp;
output wire [7:0] out;
- bar # (.WIDTH(8)) bar_instance (clk, rst, inp, out);
+ attrib03_bar # (.WIDTH(8)) bar_instance (clk, rst, inp, out);
endmodule
diff --git a/tests/simple/attrib04_net_var.v b/tests/simple/attrib04_net_var.v
index 8b5523406..98826e971 100644
--- a/tests/simple/attrib04_net_var.v
+++ b/tests/simple/attrib04_net_var.v
@@ -1,4 +1,4 @@
-module bar(clk, rst, inp, out);
+module attrib04_bar(clk, rst, inp, out);
input wire clk;
input wire rst;
input wire inp;
@@ -21,12 +21,12 @@ module bar(clk, rst, inp, out);
endmodule
-module foo(clk, rst, inp, out);
+module attrib04_foo(clk, rst, inp, out);
input wire clk;
input wire rst;
input wire inp;
output wire out;
- bar bar_instance (clk, rst, inp, out);
+ attrib04_bar bar_instance (clk, rst, inp, out);
endmodule
diff --git a/tests/simple/attrib05_port_conn.v.DISABLED b/tests/simple/attrib05_port_conn.v.DISABLED
index e20e66319..8cc471f4e 100644
--- a/tests/simple/attrib05_port_conn.v.DISABLED
+++ b/tests/simple/attrib05_port_conn.v.DISABLED
@@ -1,4 +1,4 @@
-module bar(clk, rst, inp, out);
+module attrib05_bar(clk, rst, inp, out);
input wire clk;
input wire rst;
input wire inp;
@@ -10,12 +10,12 @@ module bar(clk, rst, inp, out);
endmodule
-module foo(clk, rst, inp, out);
+module attrib05_foo(clk, rst, inp, out);
input wire clk;
input wire rst;
input wire inp;
output wire out;
- bar bar_instance ( (* clock_connected *) clk, rst, (* this_is_the_input *) inp, out);
+ attrib05_bar bar_instance ( (* clock_connected *) clk, rst, (* this_is_the_input *) inp, out);
endmodule
diff --git a/tests/simple/attrib06_operator_suffix.v b/tests/simple/attrib06_operator_suffix.v
index e21173c58..2bc136f9a 100644
--- a/tests/simple/attrib06_operator_suffix.v
+++ b/tests/simple/attrib06_operator_suffix.v
@@ -1,4 +1,4 @@
-module bar(clk, rst, inp_a, inp_b, out);
+module attrib06_bar(clk, rst, inp_a, inp_b, out);
input wire clk;
input wire rst;
input wire [7:0] inp_a;
@@ -11,13 +11,13 @@ module bar(clk, rst, inp_a, inp_b, out);
endmodule
-module foo(clk, rst, inp_a, inp_b, out);
+module attrib06_foo(clk, rst, inp_a, inp_b, out);
input wire clk;
input wire rst;
input wire [7:0] inp_a;
input wire [7:0] inp_b;
output wire [7:0] out;
- bar bar_instance (clk, rst, inp_a, inp_b, out);
+ attrib06_bar bar_instance (clk, rst, inp_a, inp_b, out);
endmodule
diff --git a/tests/simple/attrib07_func_call.v.DISABLED b/tests/simple/attrib07_func_call.v.DISABLED
index f55ef2316..282fc5da7 100644
--- a/tests/simple/attrib07_func_call.v.DISABLED
+++ b/tests/simple/attrib07_func_call.v.DISABLED
@@ -1,4 +1,4 @@
-function [7:0] do_add;
+function [7:0] attrib07_do_add;
input [7:0] inp_a;
input [7:0] inp_b;
@@ -6,7 +6,7 @@ function [7:0] do_add;
endfunction
-module foo(clk, rst, inp_a, inp_b, out);
+module attri07_foo(clk, rst, inp_a, inp_b, out);
input wire clk;
input wire rst;
input wire [7:0] inp_a;
@@ -15,7 +15,7 @@ module foo(clk, rst, inp_a, inp_b, out);
always @(posedge clk)
if (rst) out <= 0;
- else out <= do_add (* combinational_adder *) (inp_a, inp_b);
+ else out <= attrib07_do_add (* combinational_adder *) (inp_a, inp_b);
endmodule
diff --git a/tests/simple/attrib08_mod_inst.v b/tests/simple/attrib08_mod_inst.v
index c5a32234e..759e67c7b 100644
--- a/tests/simple/attrib08_mod_inst.v
+++ b/tests/simple/attrib08_mod_inst.v
@@ -1,4 +1,4 @@
-module bar(clk, rst, inp, out);
+module attrib08_bar(clk, rst, inp, out);
input wire clk;
input wire rst;
input wire inp;
@@ -10,13 +10,13 @@ module bar(clk, rst, inp, out);
endmodule
-module foo(clk, rst, inp, out);
+module attrib08_foo(clk, rst, inp, out);
input wire clk;
input wire rst;
input wire inp;
output wire out;
(* my_module_instance = 99 *)
- bar bar_instance (clk, rst, inp, out);
+ attrib08_bar bar_instance (clk, rst, inp, out);
endmodule
diff --git a/tests/simple/attrib09_case.v b/tests/simple/attrib09_case.v
index 8551bf9d0..a72b81dda 100644
--- a/tests/simple/attrib09_case.v
+++ b/tests/simple/attrib09_case.v
@@ -1,4 +1,4 @@
-module bar(clk, rst, inp, out);
+module attrib09_bar(clk, rst, inp, out);
input wire clk;
input wire rst;
input wire [1:0] inp;
@@ -15,12 +15,12 @@ module bar(clk, rst, inp, out);
endmodule
-module foo(clk, rst, inp, out);
+module attrib09_foo(clk, rst, inp, out);
input wire clk;
input wire rst;
input wire [1:0] inp;
output wire [1:0] out;
- bar bar_instance (clk, rst, inp, out);
+ attrib09_bar bar_instance (clk, rst, inp, out);
endmodule
diff --git a/tests/simple/case_expr_const.v b/tests/simple/case_expr_const.v
new file mode 100644
index 000000000..d9169c084
--- /dev/null
+++ b/tests/simple/case_expr_const.v
@@ -0,0 +1,49 @@
+// Note: case_expr_{,non_}const.v should be modified in tandem to ensure both
+// the constant and non-constant case evaluation logic is covered
+module case_expr_const_top(
+ // expected to output all 1s
+ output reg a, b, c, d, e, f, g, h
+);
+ initial begin
+ case (2'b0)
+ 1'b0: a = 1;
+ default: a = 0;
+ endcase
+ case (2'sb11)
+ 2'sb01: b = 0;
+ 1'sb1: b = 1;
+ endcase
+ case (2'sb11)
+ 1'sb0: c = 0;
+ 1'sb1: c = 1;
+ endcase
+ case (2'sb11)
+ 1'b0: d = 0;
+ 1'sb1: d = 0;
+ default: d = 1;
+ endcase
+ case (2'b11)
+ 1'sb0: e = 0;
+ 1'sb1: e = 0;
+ default: e = 1;
+ endcase
+ case (1'sb1)
+ 1'sb0: f = 0;
+ 2'sb11: f = 1;
+ default: f = 0;
+ endcase
+ case (1'sb1)
+ 1'sb0: g = 0;
+ 3'b0: g = 0;
+ 2'sb11: g = 0;
+ default: g = 1;
+ endcase
+ case (1'sb1)
+ 1'sb0: h = 0;
+ 1'b1: h = 1;
+ 3'b0: h = 0;
+ 2'sb11: h = 0;
+ default: h = 0;
+ endcase
+ end
+endmodule
diff --git a/tests/simple/case_expr_extend.sv b/tests/simple/case_expr_extend.sv
new file mode 100644
index 000000000..d4ca2aa9b
--- /dev/null
+++ b/tests/simple/case_expr_extend.sv
@@ -0,0 +1,11 @@
+module top(
+ output logic [5:0] out
+);
+initial begin
+ out = '0;
+ case (1'b1 << 1)
+ 2'b10: out = '1;
+ default: out = '0;
+ endcase
+end
+endmodule
diff --git a/tests/simple/case_expr_non_const.v b/tests/simple/case_expr_non_const.v
new file mode 100644
index 000000000..6dfc2e54e
--- /dev/null
+++ b/tests/simple/case_expr_non_const.v
@@ -0,0 +1,59 @@
+// Note: case_expr_{,non_}const.v should be modified in tandem to ensure both
+// the constant and non-constant case evaluation logic is covered
+module case_expr_non_const_top(
+ // expected to output all 1s
+ output reg a, b, c, d, e, f, g, h
+);
+ reg x_1b0 = 1'b0;
+ reg x_1b1 = 1'b1;
+ reg signed x_1sb0 = 1'sb0;
+ reg signed x_1sb1 = 1'sb1;
+ reg [1:0] x_2b0 = 2'b0;
+ reg [1:0] x_2b11 = 2'b11;
+ reg signed [1:0] x_2sb01 = 2'sb01;
+ reg signed [1:0] x_2sb11 = 2'sb11;
+ reg [2:0] x_3b0 = 3'b0;
+
+ initial begin
+ case (x_2b0)
+ x_1b0: a = 1;
+ default: a = 0;
+ endcase
+ case (x_2sb11)
+ x_2sb01: b = 0;
+ x_1sb1: b = 1;
+ endcase
+ case (x_2sb11)
+ x_1sb0: c = 0;
+ x_1sb1: c = 1;
+ endcase
+ case (x_2sb11)
+ x_1b0: d = 0;
+ x_1sb1: d = 0;
+ default: d = 1;
+ endcase
+ case (x_2b11)
+ x_1sb0: e = 0;
+ x_1sb1: e = 0;
+ default: e = 1;
+ endcase
+ case (x_1sb1)
+ x_1sb0: f = 0;
+ x_2sb11: f = 1;
+ default: f = 0;
+ endcase
+ case (x_1sb1)
+ x_1sb0: g = 0;
+ x_3b0: g = 0;
+ x_2sb11: g = 0;
+ default: g = 1;
+ endcase
+ case (x_1sb1)
+ x_1sb0: h = 0;
+ x_1b1: h = 1;
+ x_3b0: h = 0;
+ x_2sb11: h = 0;
+ default: h = 0;
+ endcase
+ end
+endmodule
diff --git a/tests/simple/case_expr_query.sv b/tests/simple/case_expr_query.sv
new file mode 100644
index 000000000..844dfb713
--- /dev/null
+++ b/tests/simple/case_expr_query.sv
@@ -0,0 +1,32 @@
+module top(
+ output logic [5:0] out
+);
+initial begin
+ out = '0;
+ case ($bits (out)) 6:
+ case ($size (out)) 6:
+ case ($high (out)) 5:
+ case ($low (out)) 0:
+ case ($left (out)) 5:
+ case ($right(out)) 0:
+ case (6) $bits (out):
+ case (6) $size (out):
+ case (5) $high (out):
+ case (0) $low (out):
+ case (5) $left (out):
+ case (0) $right(out):
+ out = '1;
+ endcase
+ endcase
+ endcase
+ endcase
+ endcase
+ endcase
+ endcase
+ endcase
+ endcase
+ endcase
+ endcase
+ endcase
+end
+endmodule
diff --git a/tests/simple/case_large.v b/tests/simple/case_large.v
new file mode 100644
index 000000000..ec8ed6038
--- /dev/null
+++ b/tests/simple/case_large.v
@@ -0,0 +1,273 @@
+module case_lage_top (
+ input wire [127:0] x,
+ output reg [31:0] y
+);
+ localparam A = 32'hDEAD_BEEF;
+ localparam B = 32'h0BAD_0B01;
+ localparam C = 32'hC001_D00D;
+ localparam D = 32'h1234_5678;
+
+ always @*
+ case (x)
+
+ {C,A,D,B}: y = 142;
+ {C,A,D,A}: y = 141;
+ {D,D,A,A}: y = 241;
+ {A,C,C,D}: y = 44;
+ {A,A,A,C}: y = 3;
+ {A,B,A,C}: y = 19;
+ {A,D,C,C}: y = 59;
+ {A,A,C,C}: y = 11;
+ {D,C,B,B}: y = 230;
+ {A,A,D,D}: y = 16;
+ {A,C,A,A}: y = 33;
+ {A,D,D,D}: y = 64;
+ {D,B,C,B}: y = 218;
+ {A,C,B,D}: y = 40;
+ {C,A,B,B}: y = 134;
+ {A,C,C,C}: y = 43;
+ {D,A,D,D}: y = 208;
+ {A,B,C,A}: y = 25;
+ {B,A,B,B}: y = 70;
+ {A,C,B,B}: y = 38;
+ {C,C,C,B}: y = 170;
+ {C,D,A,C}: y = 179;
+ {B,C,D,B}: y = 110;
+ {A,D,A,C}: y = 51;
+ {C,C,B,B}: y = 166;
+ {D,D,D,B}: y = 254;
+ {C,A,D,C}: y = 143;
+ {C,D,D,B}: y = 190;
+ {C,B,A,A}: y = 145;
+ {C,B,A,C}: y = 147;
+ {B,C,C,B}: y = 106;
+ {C,D,C,A}: y = 185;
+ {C,D,B,D}: y = 184;
+ {D,D,D,D}: y = 256;
+ {D,C,C,C}: y = 235;
+ {D,C,D,B}: y = 238;
+ {A,B,D,C}: y = 31;
+ {A,C,A,D}: y = 36;
+ {C,B,C,B}: y = 154;
+ {A,B,A,A}: y = 17;
+ {C,B,B,A}: y = 149;
+ {B,B,D,C}: y = 95;
+ {B,D,C,B}: y = 122;
+ {D,B,A,A}: y = 209;
+ {B,A,B,A}: y = 69;
+ {B,A,D,A}: y = 77;
+ {A,B,B,B}: y = 22;
+ {C,C,C,C}: y = 171;
+ {C,A,C,B}: y = 138;
+ {B,A,D,D}: y = 80;
+ {C,D,D,C}: y = 191;
+ {B,A,A,C}: y = 67;
+ {D,C,D,C}: y = 239;
+ {C,D,D,D}: y = 192;
+ {C,D,B,B}: y = 182;
+ {B,B,A,C}: y = 83;
+ {D,A,A,D}: y = 196;
+ {A,C,C,B}: y = 42;
+ {B,C,A,A}: y = 97;
+ {A,D,B,A}: y = 53;
+ {D,D,B,C}: y = 247;
+ {A,A,C,A}: y = 9;
+ {D,A,C,B}: y = 202;
+ {A,C,B,C}: y = 39;
+ {B,C,B,A}: y = 101;
+ {B,B,B,C}: y = 87;
+ {C,B,A,B}: y = 146;
+ {B,D,A,D}: y = 116;
+ {A,B,D,D}: y = 32;
+ {B,A,B,C}: y = 71;
+ {C,A,A,A}: y = 129;
+ {B,A,D,C}: y = 79;
+ {B,A,C,B}: y = 74;
+ {B,B,D,B}: y = 94;
+ {B,B,C,C}: y = 91;
+ {D,C,C,A}: y = 233;
+ {C,A,B,A}: y = 133;
+ {D,A,B,A}: y = 197;
+ {D,B,B,D}: y = 216;
+ {C,C,A,C}: y = 163;
+ {D,D,B,A}: y = 245;
+ {B,A,D,B}: y = 78;
+ {A,B,C,D}: y = 28;
+ {C,C,C,D}: y = 172;
+ {D,C,A,D}: y = 228;
+ {A,C,D,A}: y = 45;
+ {B,D,C,C}: y = 123;
+ {C,B,A,D}: y = 148;
+ {B,D,B,B}: y = 118;
+ {A,D,A,B}: y = 50;
+ {C,B,B,C}: y = 151;
+ {A,A,A,A}: y = 1;
+ {A,A,B,B}: y = 6;
+ {B,B,B,B}: y = 86;
+ {A,D,A,A}: y = 49;
+ {A,A,A,B}: y = 2;
+ {B,D,D,A}: y = 125;
+ {C,C,D,B}: y = 174;
+ {D,A,D,B}: y = 206;
+ {D,D,B,D}: y = 248;
+ {A,A,A,D}: y = 4;
+ {B,A,A,B}: y = 66;
+ {B,C,C,A}: y = 105;
+ {B,C,C,C}: y = 107;
+ {D,D,D,C}: y = 255;
+ {B,C,D,D}: y = 112;
+ {A,D,B,C}: y = 55;
+ {C,C,C,A}: y = 169;
+ {C,D,B,C}: y = 183;
+ {A,A,B,D}: y = 8;
+ {D,C,B,A}: y = 229;
+ {C,B,D,A}: y = 157;
+ {A,D,D,C}: y = 63;
+ {D,A,D,A}: y = 205;
+ {A,A,B,C}: y = 7;
+ {A,C,A,B}: y = 34;
+ {C,B,D,C}: y = 159;
+ {C,C,D,D}: y = 176;
+ {D,D,D,A}: y = 253;
+ {A,B,B,D}: y = 24;
+ {B,B,C,A}: y = 89;
+ {B,D,C,A}: y = 121;
+ {A,B,C,C}: y = 27;
+ {A,A,D,C}: y = 15;
+ {A,B,B,A}: y = 21;
+ {A,D,A,D}: y = 52;
+ {D,D,C,C}: y = 251;
+ {C,D,A,B}: y = 178;
+ {A,A,D,B}: y = 14;
+ {D,B,D,B}: y = 222;
+ {A,C,C,A}: y = 41;
+ {D,D,A,C}: y = 243;
+ {A,C,D,B}: y = 46;
+ {B,B,B,D}: y = 88;
+ {D,B,B,B}: y = 214;
+ {C,C,B,D}: y = 168;
+ {A,D,D,A}: y = 61;
+ {D,A,C,C}: y = 203;
+ {D,C,A,C}: y = 227;
+ {C,D,C,D}: y = 188;
+ {D,B,D,D}: y = 224;
+ {A,C,D,C}: y = 47;
+ {B,A,B,D}: y = 72;
+ {A,B,B,C}: y = 23;
+ {C,C,D,A}: y = 173;
+ {D,B,C,C}: y = 219;
+ {D,B,C,A}: y = 217;
+ {A,D,C,D}: y = 60;
+ {B,B,D,A}: y = 93;
+ {A,D,C,A}: y = 57;
+ {C,C,A,A}: y = 161;
+ {C,B,B,D}: y = 152;
+ {B,B,B,A}: y = 85;
+ {B,D,A,A}: y = 113;
+ {D,C,D,A}: y = 237;
+ {B,C,B,C}: y = 103;
+ {A,B,C,B}: y = 26;
+ {C,D,A,D}: y = 180;
+ {A,D,B,D}: y = 56;
+ {D,C,A,B}: y = 226;
+ {D,B,B,C}: y = 215;
+ {D,A,B,C}: y = 199;
+ {B,D,A,C}: y = 115;
+ {C,B,C,D}: y = 156;
+ {B,D,D,B}: y = 126;
+ {D,D,C,B}: y = 250;
+ {D,C,C,D}: y = 236;
+ {B,C,B,D}: y = 104;
+ {C,B,C,A}: y = 153;
+ {C,B,B,B}: y = 150;
+ {C,D,C,B}: y = 186;
+ {C,D,C,C}: y = 187;
+ {A,D,B,B}: y = 54;
+ {D,C,C,B}: y = 234;
+ {C,B,D,D}: y = 160;
+ {A,B,A,D}: y = 20;
+ {C,C,B,A}: y = 165;
+ {C,D,D,A}: y = 189;
+ {C,C,D,C}: y = 175;
+ {D,B,D,C}: y = 223;
+ {B,C,A,B}: y = 98;
+ {C,C,A,B}: y = 162;
+ {B,C,D,A}: y = 109;
+ {D,A,B,D}: y = 200;
+ {B,D,C,D}: y = 124;
+ {D,D,C,A}: y = 249;
+ {B,A,C,C}: y = 75;
+ {A,A,C,B}: y = 10;
+ {C,A,B,D}: y = 136;
+ {B,B,C,D}: y = 92;
+ {D,D,C,D}: y = 252;
+ {B,C,A,D}: y = 100;
+ {C,A,C,C}: y = 139;
+ {C,A,C,D}: y = 140;
+ {D,C,A,A}: y = 225;
+ {A,D,C,B}: y = 58;
+ {D,B,C,D}: y = 220;
+ {D,C,B,D}: y = 232;
+ {B,A,C,D}: y = 76;
+ {B,B,D,D}: y = 96;
+ {D,D,B,B}: y = 246;
+ {C,D,A,A}: y = 177;
+ {D,D,A,B}: y = 242;
+ {A,A,D,A}: y = 13;
+ {B,B,A,D}: y = 84;
+ {B,C,D,C}: y = 111;
+ {D,A,A,B}: y = 194;
+ {C,A,B,C}: y = 135;
+ {D,A,A,C}: y = 195;
+ {B,B,A,B}: y = 82;
+ {D,C,D,D}: y = 240;
+ {B,C,C,D}: y = 108;
+ {D,B,A,C}: y = 211;
+ {A,C,D,D}: y = 48;
+ {D,A,A,A}: y = 193;
+ {C,A,A,B}: y = 130;
+ {D,B,A,D}: y = 212;
+ {D,A,B,B}: y = 198;
+ {A,C,B,A}: y = 37;
+ {B,D,B,D}: y = 120;
+ {C,C,B,C}: y = 167;
+ {D,B,A,B}: y = 210;
+ {A,B,A,B}: y = 18;
+ {B,C,B,B}: y = 102;
+ {B,B,A,A}: y = 81;
+ {D,D,A,D}: y = 244;
+ {A,B,D,B}: y = 30;
+ {A,C,A,C}: y = 35;
+ {A,A,C,D}: y = 12;
+ {B,D,B,C}: y = 119;
+ {B,C,A,C}: y = 99;
+ {D,A,C,A}: y = 201;
+ {B,A,A,D}: y = 68;
+ {C,A,A,D}: y = 132;
+ {B,A,C,A}: y = 73;
+ {C,C,A,D}: y = 164;
+ {B,D,B,A}: y = 117;
+ {A,D,D,B}: y = 62;
+ {B,D,D,C}: y = 127;
+ {A,B,D,A}: y = 29;
+ {C,D,B,A}: y = 181;
+ {B,B,C,B}: y = 90;
+ {B,D,A,B}: y = 114;
+ {B,D,D,D}: y = 128;
+ {C,A,C,A}: y = 137;
+ {A,A,B,A}: y = 5;
+ {C,A,D,D}: y = 144;
+ {D,C,B,C}: y = 231;
+ {D,A,C,D}: y = 204;
+ {C,A,A,C}: y = 131;
+ {C,B,D,B}: y = 158;
+ {B,A,A,A}: y = 65;
+ {D,A,D,C}: y = 207;
+ {D,B,B,A}: y = 213;
+ {D,B,D,A}: y = 221;
+ {C,B,C,C}: y = 155;
+
+ default: y = 0;
+
+ endcase
+endmodule
diff --git a/tests/simple/const_branch_finish.v b/tests/simple/const_branch_finish.v
index f585be87a..7e365eeb4 100644
--- a/tests/simple/const_branch_finish.v
+++ b/tests/simple/const_branch_finish.v
@@ -4,7 +4,7 @@
$finish; \
end
-module top;
+module case_branch_finish_top;
parameter WIDTH = 32;
integer j;
initial begin
diff --git a/tests/simple/const_fold_func.v b/tests/simple/const_fold_func.v
index ee2f12e06..b3f476ce3 100644
--- a/tests/simple/const_fold_func.v
+++ b/tests/simple/const_fold_func.v
@@ -1,4 +1,4 @@
-module top(
+module const_fold_func_top(
input wire [3:0] inp,
output wire [3:0] out1, out2, out3, out4, out5,
output reg [3:0] out6
diff --git a/tests/simple/const_func_shadow.v b/tests/simple/const_func_shadow.v
index ca63606d9..fb4f148f6 100644
--- a/tests/simple/const_func_shadow.v
+++ b/tests/simple/const_func_shadow.v
@@ -1,4 +1,4 @@
-module top(w, x, y, z);
+module const_func_shadow_top(w, x, y, z);
function [11:0] func;
input reg [2:0] x;
input reg [2:0] y;
diff --git a/tests/simple/defvalue.sv b/tests/simple/defvalue.sv
index b0a087ecb..77d7ba26b 100644
--- a/tests/simple/defvalue.sv
+++ b/tests/simple/defvalue.sv
@@ -1,4 +1,4 @@
-module top(input clock, input [3:0] delta, output [3:0] cnt1, cnt2);
+module defvalue_top(input clock, input [3:0] delta, output [3:0] cnt1, cnt2);
cnt #(1) foo (.clock, .cnt(cnt1), .delta);
cnt #(2) bar (.clock, .cnt(cnt2));
endmodule
diff --git a/tests/simple/func_block.v b/tests/simple/func_block.v
index be759d1a9..0ac7ca3bf 100644
--- a/tests/simple/func_block.v
+++ b/tests/simple/func_block.v
@@ -1,6 +1,6 @@
`default_nettype none
-module top(inp, out1, out2, out3);
+module func_block_top(inp, out1, out2, out3);
input wire [31:0] inp;
function automatic [31:0] func1;
diff --git a/tests/simple/func_recurse.v b/tests/simple/func_recurse.v
index d61c8cc06..02cfbcddf 100644
--- a/tests/simple/func_recurse.v
+++ b/tests/simple/func_recurse.v
@@ -1,4 +1,4 @@
-module top(
+module func_recurse_top(
input wire [3:0] inp,
output wire [3:0] out1, out2
);
diff --git a/tests/simple/func_width_scope.v b/tests/simple/func_width_scope.v
index ce81e894e..2f82988ae 100644
--- a/tests/simple/func_width_scope.v
+++ b/tests/simple/func_width_scope.v
@@ -1,4 +1,4 @@
-module top(inp, out1, out2);
+module func_width_scope_top(inp, out1, out2);
input wire signed inp;
localparam WIDTH_A = 5;
diff --git a/tests/simple/genblk_collide.v b/tests/simple/genblk_collide.v
index f42dd2cfc..118c0b008 100644
--- a/tests/simple/genblk_collide.v
+++ b/tests/simple/genblk_collide.v
@@ -1,6 +1,6 @@
`default_nettype none
-module top1;
+module genblock_collide_top1;
generate
if (1) begin : foo
if (1) begin : bar
@@ -12,7 +12,7 @@ module top1;
endgenerate
endmodule
-module top2;
+module genblock_collide_top2;
genvar i;
generate
if (1) begin : foo
diff --git a/tests/simple/genblk_dive.v b/tests/simple/genblk_dive.v
index 98d0e1f4b..ca0c0d4a1 100644
--- a/tests/simple/genblk_dive.v
+++ b/tests/simple/genblk_dive.v
@@ -1,5 +1,5 @@
`default_nettype none
-module top(output wire x);
+module genblk_dive_top(output wire x);
generate
if (1) begin : Z
if (1) begin : A
diff --git a/tests/simple/genblk_order.v b/tests/simple/genblk_order.v
index 7c3a7a756..c80c1ac1a 100644
--- a/tests/simple/genblk_order.v
+++ b/tests/simple/genblk_order.v
@@ -1,5 +1,5 @@
`default_nettype none
-module top(
+module genblk_order_top(
output wire out1,
output wire out2
);
diff --git a/tests/simple/genblk_port_shadow.v b/tests/simple/genblk_port_shadow.v
index a04631a20..c1348632c 100644
--- a/tests/simple/genblk_port_shadow.v
+++ b/tests/simple/genblk_port_shadow.v
@@ -1,4 +1,4 @@
-module top(x);
+module genblock_port_shadow_top(x);
generate
if (1) begin : blk
wire x;
diff --git a/tests/simple/hierarchy.v b/tests/simple/hierarchy.v
index 123afaeab..b03044fde 100644
--- a/tests/simple/hierarchy.v
+++ b/tests/simple/hierarchy.v
@@ -1,6 +1,6 @@
(* top *)
-module top(a, b, y1, y2, y3, y4);
+module hierarchy_top(a, b, y1, y2, y3, y4);
input [3:0] a;
input signed [3:0] b;
output [7:0] y1, y2, y3, y4;
diff --git a/tests/simple/ifdef_1.v b/tests/simple/ifdef_1.v
index fa962355c..f1358185c 100644
--- a/tests/simple/ifdef_1.v
+++ b/tests/simple/ifdef_1.v
@@ -1,4 +1,4 @@
-module top(o1, o2, o3, o4);
+module ifdef_1_top(o1, o2, o3, o4);
`define FAIL input wire not_a_port;
diff --git a/tests/simple/ifdef_2.v b/tests/simple/ifdef_2.v
index 6dd89efed..9fae7570d 100644
--- a/tests/simple/ifdef_2.v
+++ b/tests/simple/ifdef_2.v
@@ -1,4 +1,4 @@
-module top(o1, o2, o3);
+module ifdef_2_top(o1, o2, o3);
output wire o1;
diff --git a/tests/simple/lesser_size_cast.sv b/tests/simple/lesser_size_cast.sv
new file mode 100644
index 000000000..8c0bc9814
--- /dev/null
+++ b/tests/simple/lesser_size_cast.sv
@@ -0,0 +1,7 @@
+module top (
+ input signed [1:0] a,
+ input signed [2:0] b,
+ output signed [4:0] c
+);
+ assign c = 2'(a) * b;
+endmodule
diff --git a/tests/simple/local_loop_var.sv b/tests/simple/local_loop_var.sv
index 46b4e5c22..42860e218 100644
--- a/tests/simple/local_loop_var.sv
+++ b/tests/simple/local_loop_var.sv
@@ -1,4 +1,4 @@
-module top(out);
+module local_loop_top(out);
output integer out;
initial begin
integer i;
diff --git a/tests/simple/loop_prefix_case.v b/tests/simple/loop_prefix_case.v
new file mode 100644
index 000000000..0cfa00547
--- /dev/null
+++ b/tests/simple/loop_prefix_case.v
@@ -0,0 +1,18 @@
+module loop_prefix_case_top(
+ input wire x,
+ output reg y
+);
+ localparam I = 1;
+ genvar i;
+ generate
+ for (i = 0; i < 1; i = i + 1) begin : blk
+ wire [i:i] z = x;
+ end
+ endgenerate
+ always @* begin
+ case (blk[I - 1].z)
+ 1: y = 0;
+ 0: y = 1;
+ endcase
+ end
+endmodule
diff --git a/tests/simple/loop_var_shadow.v b/tests/simple/loop_var_shadow.v
index 0222a4493..b75a15ab0 100644
--- a/tests/simple/loop_var_shadow.v
+++ b/tests/simple/loop_var_shadow.v
@@ -1,4 +1,4 @@
-module top(out);
+module loop_var_shadow_top(out);
genvar i;
generate
for (i = 0; i < 2; i = i + 1) begin : loop
diff --git a/tests/simple/macro_arg_spaces.sv b/tests/simple/macro_arg_spaces.sv
index 75c4cd136..5fc9e2881 100644
--- a/tests/simple/macro_arg_spaces.sv
+++ b/tests/simple/macro_arg_spaces.sv
@@ -1,4 +1,4 @@
-module top(
+module macro_arg_spaces_top(
input wire [31:0] i,
output wire [31:0] x, y, z
);
diff --git a/tests/simple/macro_arg_surrounding_spaces.v b/tests/simple/macro_arg_surrounding_spaces.v
index 3dbb5ea01..e0239c08b 100644
--- a/tests/simple/macro_arg_surrounding_spaces.v
+++ b/tests/simple/macro_arg_surrounding_spaces.v
@@ -1,4 +1,4 @@
-module top(
+module macr_arg_surrounding_spaces_top(
IDENT_V_,
IDENT_W_,
IDENT_X_,
diff --git a/tests/simple/matching_end_labels.sv b/tests/simple/matching_end_labels.sv
new file mode 100644
index 000000000..2d42e7e10
--- /dev/null
+++ b/tests/simple/matching_end_labels.sv
@@ -0,0 +1,29 @@
+module matching_end_labels_top(
+ output reg [7:0]
+ out1, out2, out3, out4
+);
+ initial begin
+ begin : blk1
+ reg x;
+ x = 1;
+ end
+ out1 = blk1.x;
+ begin : blk2
+ reg x;
+ x = 2;
+ end : blk2
+ out2 = blk2.x;
+ end
+ if (1) begin
+ if (1) begin : blk3
+ reg x;
+ assign x = 3;
+ end
+ assign out3 = blk3.x;
+ if (1) begin : blk4
+ reg x;
+ assign x = 4;
+ end : blk4
+ assign out4 = blk4.x;
+ end
+endmodule
diff --git a/tests/simple/mem2reg_bounds_tern.v b/tests/simple/mem2reg_bounds_tern.v
new file mode 100644
index 000000000..0e6852fe7
--- /dev/null
+++ b/tests/simple/mem2reg_bounds_tern.v
@@ -0,0 +1,19 @@
+module mem2reg_bounds_term_top(
+ input clk,
+ input wire [1:0] sel,
+ input wire [7:0] base,
+ output reg [7:0] line
+);
+ reg [0:7] mem [0:2];
+
+ generate
+ genvar i;
+ for (i = 0; i < 4; i = i + 1) begin : gen
+ always @(posedge clk)
+ mem[i] <= i == 0 ? base : mem[i - 1] + 1;
+ end
+ endgenerate
+
+ always @(posedge clk)
+ line = mem[sel];
+endmodule
diff --git a/tests/simple/memwr_port_connection.sv b/tests/simple/memwr_port_connection.sv
new file mode 100644
index 000000000..5bf414e08
--- /dev/null
+++ b/tests/simple/memwr_port_connection.sv
@@ -0,0 +1,13 @@
+module producer(
+ output logic [3:0] out
+);
+ assign out = 4'hA;
+endmodule
+
+module top(
+ output logic [3:0] out
+);
+ logic [3:0] v[0:0];
+ producer p(v[0]);
+ assign out = v[0];
+endmodule
diff --git a/tests/simple/module_scope.v b/tests/simple/module_scope.v
new file mode 100644
index 000000000..d07783912
--- /dev/null
+++ b/tests/simple/module_scope.v
@@ -0,0 +1,29 @@
+`default_nettype none
+
+module module_scope_Example(o1, o2);
+ parameter [31:0] v1 = 10;
+ parameter [31:0] v2 = 20;
+ output [31:0] o1, o2;
+ assign module_scope_Example.o1 = module_scope_Example.v1;
+ assign module_scope_Example.o2 = module_scope_Example.v2;
+endmodule
+
+module module_scope_ExampleLong(o1, o2);
+ parameter [31:0] ThisIsAnExtremelyLongParameterNameToTriggerTheSHA1Checksum1 = 10;
+ parameter [31:0] ThisIsAnExtremelyLongParameterNameToTriggerTheSHA1Checksum2 = 20;
+ output [31:0] o1, o2;
+ assign module_scope_ExampleLong.o1 = module_scope_ExampleLong.ThisIsAnExtremelyLongParameterNameToTriggerTheSHA1Checksum1;
+ assign module_scope_ExampleLong.o2 = module_scope_ExampleLong.ThisIsAnExtremelyLongParameterNameToTriggerTheSHA1Checksum2;
+endmodule
+
+module module_scope_top(
+ output [31:0] a1, a2, b1, b2, c1, c2,
+ output [31:0] d1, d2, e1, e2, f1, f2
+);
+ module_scope_Example a(a1, a2);
+ module_scope_Example #(1) b(b1, b2);
+ module_scope_Example #(1, 2) c(c1, c2);
+ module_scope_ExampleLong d(d1, d2);
+ module_scope_ExampleLong #(1) e(e1, e2);
+ module_scope_ExampleLong #(1, 2) f(f1, f2);
+endmodule
diff --git a/tests/simple/module_scope_case.v b/tests/simple/module_scope_case.v
new file mode 100644
index 000000000..bceba4424
--- /dev/null
+++ b/tests/simple/module_scope_case.v
@@ -0,0 +1,11 @@
+module module_scope_case_top(
+ input wire x,
+ output reg y
+);
+ always @* begin
+ case (module_scope_case_top.x)
+ 1: module_scope_case_top.y = 0;
+ 0: module_scope_case_top.y = 1;
+ endcase
+ end
+endmodule
diff --git a/tests/simple/named_genblk.v b/tests/simple/named_genblk.v
index b8300fc4d..b98b7c8ce 100644
--- a/tests/simple/named_genblk.v
+++ b/tests/simple/named_genblk.v
@@ -1,5 +1,5 @@
`default_nettype none
-module top;
+module named_genblk_top;
generate
if (1) begin
wire t;
diff --git a/tests/simple/nested_genblk_resolve.v b/tests/simple/nested_genblk_resolve.v
index da5593f8a..70bbc611b 100644
--- a/tests/simple/nested_genblk_resolve.v
+++ b/tests/simple/nested_genblk_resolve.v
@@ -1,5 +1,5 @@
`default_nettype none
-module top;
+module nested_genblk_resolve_top;
generate
if (1) begin
wire x;
diff --git a/tests/simple/signed_full_slice.v b/tests/simple/signed_full_slice.v
new file mode 100644
index 000000000..f8a331578
--- /dev/null
+++ b/tests/simple/signed_full_slice.v
@@ -0,0 +1,29 @@
+module pass_through_a(
+ input wire [31:0] inp,
+ output wire [31:0] out
+);
+ assign out[31:0] = inp[31:0];
+endmodule
+
+module top_a(
+ input wire signed [31:0] inp,
+ output wire signed [31:0] out
+);
+ pass_through_a pt(inp[31:0], out[31:0]);
+endmodule
+
+// tests both module declaration orderings
+
+module top_b(
+ input wire signed [31:0] inp,
+ output wire signed [31:0] out
+);
+ pass_through_b pt(inp[31:0], out[31:0]);
+endmodule
+
+module pass_through_b(
+ input wire [31:0] inp,
+ output wire [31:0] out
+);
+ assign out[31:0] = inp[31:0];
+endmodule
diff --git a/tests/simple/string_format.v b/tests/simple/string_format.v
index ce45ca1e9..cb7b419ac 100644
--- a/tests/simple/string_format.v
+++ b/tests/simple/string_format.v
@@ -1,4 +1,4 @@
-module top;
+module string_format_top;
parameter STR = "something interesting";
initial begin
$display("A: %s", STR);
diff --git a/tests/simple/unnamed_block_decl.sv b/tests/simple/unnamed_block_decl.sv
index e81b457a8..e78c577da 100644
--- a/tests/simple/unnamed_block_decl.sv
+++ b/tests/simple/unnamed_block_decl.sv
@@ -1,4 +1,4 @@
-module top(z);
+module unnamed_block_decl(z);
output integer z;
initial begin
integer x;
diff --git a/tests/simple/verilog_primitives.v b/tests/simple/verilog_primitives.v
new file mode 100644
index 000000000..0ee07393b
--- /dev/null
+++ b/tests/simple/verilog_primitives.v
@@ -0,0 +1,15 @@
+module verilog_primitives (
+ input wire in1, in2, in3,
+ output wire out_buf0, out_buf1, out_buf2, out_buf3, out_buf4,
+ output wire out_not0, out_not1, out_not2,
+ output wire out_xnor
+);
+
+buf u_buf0 (out_buf0, in1);
+buf u_buf1 (out_buf1, out_buf2, out_buf3, out_buf4, in2);
+
+not u_not0 (out_not0, out_not1, out_not2, in1);
+
+xnor u_xnor0 (out_xnor, in1, in2, in3);
+
+endmodule
diff --git a/tests/simple/vloghammer.v b/tests/simple/vloghammer.v
index 3bb3cf992..5fcedbff1 100644
--- a/tests/simple/vloghammer.v
+++ b/tests/simple/vloghammer.v
@@ -1,6 +1,6 @@
// test cases found using vloghammer
-// https://github.com/cliffordwolf/VlogHammer
+// https://github.com/YosysHQ/VlogHammer
module test01(a, y);
input [7:0] a;
diff --git a/tests/simple/wandwor.v b/tests/simple/wandwor.v
index 34404aa26..40502acfc 100644
--- a/tests/simple/wandwor.v
+++ b/tests/simple/wandwor.v
@@ -5,9 +5,9 @@ module wandwor_test0 (A, B, C, D, X, Y, Z);
output Z;
assign X = A, X = B, Y = C, Y = D;
- foo foo_0 (C, D, X);
- foo foo_1 (A, B, Y);
- foo foo_2 (X, Y, Z);
+ wandwor_foo foo_0 (C, D, X);
+ wandwor_foo foo_1 (A, B, Y);
+ wandwor_foo foo_2 (X, Y, Z);
endmodule
module wandwor_test1 (A, B, C, D, X, Y, Z);
@@ -16,7 +16,7 @@ module wandwor_test1 (A, B, C, D, X, Y, Z);
output wand [3:0] Y;
output Z;
- bar bar_inst (
+ wandwor_bar bar_inst (
.I0({A, B}),
.I1({B, A}),
.O({X, Y})
@@ -27,10 +27,10 @@ module wandwor_test1 (A, B, C, D, X, Y, Z);
assign Z = ^{X,Y};
endmodule
-module foo(input I0, I1, output O);
+module wandwor_foo(input I0, I1, output O);
assign O = I0 ^ I1;
endmodule
-module bar(input [7:0] I0, I1, output [7:0] O);
+module wandwor_bar(input [7:0] I0, I1, output [7:0] O);
assign O = I0 + I1;
endmodule
diff --git a/tests/simple_abc9/abc9.box b/tests/simple_abc9/abc9.box
deleted file mode 100644
index b3c88437c..000000000
--- a/tests/simple_abc9/abc9.box
+++ /dev/null
@@ -1,3 +0,0 @@
-MUXF8 1 0 3 1
-#I0 I1 S
-0 0 0 # O
diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v
index 5e969c614..fba089b1f 100644
--- a/tests/simple_abc9/abc9.v
+++ b/tests/simple_abc9/abc9.v
@@ -213,7 +213,7 @@ module arbiter (clk, rst, request, acknowledge, grant, grant_valid, grant_encode
input rst;
endmodule
-(* abc9_box_id=1, blackbox *)
+(* abc9_box, blackbox *)
module MUXF8(input I0, I1, S, output O);
specify
(I0 => O) = 0;
@@ -300,15 +300,29 @@ endmodule
module abc9_test036(input A, B, S, output [1:0] O);
(* keep *)
MUXF8 m (
- .I0(I0),
- .I1(I1),
+ .I0(A),
+ .I1(B),
.O(O[0]),
.S(S)
);
MUXF8 m2 (
- .I0(I0),
- .I1(I1),
+ .I0(A),
+ .I1(B),
.O(O[1]),
.S(S)
);
endmodule
+
+(* abc9_box, whitebox *)
+module MUXF7(input I0, I1, S, output O);
+assign O = S ? I1 : I0;
+specify
+ (I0 => O) = 0;
+ (I1 => O) = 0;
+ (S => O) = 0;
+endspecify
+endmodule
+
+module abc9_test037(output o);
+MUXF7 m(.I0(1'b1), .I1(1'b0), .S(o), .O(o));
+endmodule
diff --git a/tests/simple_abc9/run-test.sh b/tests/simple_abc9/run-test.sh
index b48505e29..4a5bf01a3 100755
--- a/tests/simple_abc9/run-test.sh
+++ b/tests/simple_abc9/run-test.sh
@@ -37,14 +37,18 @@ done
cp ../simple/*.v .
cp ../simple/*.sv .
+rm specify.v # bug 2675
DOLLAR='?'
-exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v *.sv EXTRA_FLAGS="-n 300 -p '\
+exec ${MAKE:-make} -f ../tools/autotest.mk $seed *.v *.sv EXTRA_FLAGS="-f \"verilog -noblackbox -specify\" -n 300 -p '\
+ read_verilog -icells -lib +/abc9_model.v; \
hierarchy; \
synth -run coarse; \
opt -full; \
techmap; \
- abc9 -lut 4 -box ../abc9.box; \
+ abc9 -lut 4; \
clean; \
- check -assert; \
+ check -assert * abc9_test037 %d; \
select -assert-none t:${DOLLAR}_NOT_ t:${DOLLAR}_AND_ %%; \
- setattr -mod -unset blackbox'"
+ setattr -mod -unset blackbox -unset whitebox'"
+
+# NOTE: Skip 'check -assert' on abc9_test037 because it intentionally has a combinatorial loop
diff --git a/tests/svinterfaces/load_and_derive.sv b/tests/svinterfaces/load_and_derive.sv
new file mode 100644
index 000000000..0de0de3b3
--- /dev/null
+++ b/tests/svinterfaces/load_and_derive.sv
@@ -0,0 +1,20 @@
+// This test checks that we correctly elaborate interfaces in modules, even if they are loaded on
+// demand. The "ondemand" module is defined in ondemand.sv in this directory and will be read as
+// part of the hierarchy pass.
+
+interface iface;
+ logic [7:0] x;
+ logic [7:0] y;
+endinterface
+
+module dut (input logic [7:0] x, output logic [7:0] y);
+ iface intf();
+ assign intf.x = x;
+ assign y = intf.y;
+
+ ondemand u(.intf);
+endmodule
+
+module ref (input logic [7:0] x, output logic [7:0] y);
+ assign y = ~x;
+endmodule
diff --git a/tests/svinterfaces/load_and_derive.ys b/tests/svinterfaces/load_and_derive.ys
new file mode 100644
index 000000000..067235ec2
--- /dev/null
+++ b/tests/svinterfaces/load_and_derive.ys
@@ -0,0 +1,6 @@
+read_verilog -sv load_and_derive.sv
+hierarchy -libdir . -check
+flatten
+equiv_make ref dut equiv
+equiv_simple
+equiv_status -assert
diff --git a/tests/svinterfaces/ondemand.sv b/tests/svinterfaces/ondemand.sv
new file mode 100644
index 000000000..70d6048f8
--- /dev/null
+++ b/tests/svinterfaces/ondemand.sv
@@ -0,0 +1,5 @@
+// This is used by the load_and_derive test.
+
+module ondemand (iface intf);
+ assign intf.y = ~intf.x;
+endmodule
diff --git a/tests/svinterfaces/run-test.sh b/tests/svinterfaces/run-test.sh
index 86567d1c1..9ef53926c 100755
--- a/tests/svinterfaces/run-test.sh
+++ b/tests/svinterfaces/run-test.sh
@@ -1,6 +1,6 @@
#/bin/bash -e
-
-
./runone.sh svinterface1
./runone.sh svinterface_at_top
+
+./run_simple.sh load_and_derive
diff --git a/tests/svinterfaces/run_simple.sh b/tests/svinterfaces/run_simple.sh
new file mode 100755
index 000000000..bce994443
--- /dev/null
+++ b/tests/svinterfaces/run_simple.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+# Run a simple test with a .ys file
+
+if [ $# != 1 ]; then
+ echo >&2 "Expected 1 argument"
+ exit 1
+fi
+
+echo -n "Test: $1 ->"
+../../yosys $1.ys >$1.log_stdout 2>$1.log_stderr || {
+ echo "ERROR!"
+ exit 1
+}
+echo "ok"
diff --git a/tests/svtypes/logic_rom.ys b/tests/svtypes/logic_rom.ys
index 7b079c136..776d2e985 100644
--- a/tests/svtypes/logic_rom.ys
+++ b/tests/svtypes/logic_rom.ys
@@ -1,3 +1,3 @@
read_verilog -sv logic_rom.sv
prep -top top
-select -assert-count 1 t:$mem r:SIZE=16 %i r:WIDTH=8 %i
+select -assert-count 1 t:$mem_v2 r:SIZE=16 %i r:WIDTH=8 %i
diff --git a/tests/svtypes/typedef_initial_and_assign.sv b/tests/svtypes/typedef_initial_and_assign.sv
new file mode 100644
index 000000000..05579947d
--- /dev/null
+++ b/tests/svtypes/typedef_initial_and_assign.sv
@@ -0,0 +1,94 @@
+package pkg;
+ typedef logic pkg_user_t;
+endpackage
+
+module top;
+ typedef logic user_t;
+
+ // Continuous assignment to a variable is legal
+ user_t var_1;
+ assign var_1 = 0;
+ assert property (var_1 == 0);
+
+ var user_t var_2;
+ assign var_2 = 0;
+ assert property (var_2 == 0);
+
+ var pkg::pkg_user_t var_3;
+ assign var_3 = 0;
+ assert property (var_3 == 0);
+
+ // Procedural assignment to a variable is legal
+ user_t var_4 = 0;
+ assert property (var_4 == 0);
+
+ user_t var_5;
+ initial var_5 = 0;
+ assert property (var_5 == 0);
+
+ var user_t var_6 = 0;
+ assert property (var_6 == 0);
+
+ var user_t var_7;
+ initial var_7 = 0;
+ assert property (var_7 == 0);
+
+ pkg::pkg_user_t var_8 = 0;
+ assert property (var_8 == 0);
+
+ pkg::pkg_user_t var_9;
+ initial var_9 = 0;
+ assert property (var_9 == 0);
+
+ var pkg::pkg_user_t var_10 = 0;
+ assert property (var_10 == 0);
+
+ var pkg::pkg_user_t var_11;
+ initial var_11 = 0;
+ assert property (var_11 == 0);
+
+ // Continuous assignment to a net is legal
+ wire user_t wire_1 = 0;
+ assert property (wire_3 == 0);
+
+ wire user_t wire_2;
+ assign wire_2 = 0;
+ assert property (wire_2 == 0);
+
+ wire pkg::pkg_user_t wire_3 = 0;
+ assert property (wire_3 == 0);
+
+ wire pkg::pkg_user_t wire_4;
+ assign wire_4 = 0;
+ assert property (wire_4 == 0);
+
+ // Mixing continuous and procedural assignments is illegal
+ user_t var_12 = 0;
+ assign var_12 = 1; // warning: reg assigned in a continuous assignment
+
+ user_t var_13;
+ initial var_13 = 0;
+ assign var_13 = 1; // warning: reg assigned in a continuous assignment
+
+ var user_t var_14 = 0;
+ assign var_14 = 1; // warning: reg assigned in a continuous assignment
+
+ var user_t var_15;
+ initial var_15 = 0;
+ assign var_15 = 1; // warning: reg assigned in a continuous assignment
+
+ pkg::pkg_user_t var_16 = 0;
+ assign var_16 = 1; // warning: reg assigned in a continuous assignment
+
+ pkg::pkg_user_t var_17;
+ initial var_17 = 0;
+ assign var_17 = 1; // warning: reg assigned in a continuous assignment
+
+ var pkg::pkg_user_t var_18 = 0;
+ assign var_18 = 1; // warning: reg assigned in a continuous assignment
+
+ var pkg::pkg_user_t var_19;
+ initial var_19 = 0;
+ assign var_19 = 1; // warning: reg assigned in a continuous assignment
+
+endmodule
diff --git a/tests/svtypes/typedef_initial_and_assign.ys b/tests/svtypes/typedef_initial_and_assign.ys
new file mode 100644
index 000000000..de456bb82
--- /dev/null
+++ b/tests/svtypes/typedef_initial_and_assign.ys
@@ -0,0 +1,14 @@
+logger -expect-no-warnings
+logger -expect warning "reg '\\var_12' is assigned in a continuous assignment" 1
+logger -expect warning "reg '\\var_13' is assigned in a continuous assignment" 1
+logger -expect warning "reg '\\var_14' is assigned in a continuous assignment" 1
+logger -expect warning "reg '\\var_15' is assigned in a continuous assignment" 1
+logger -expect warning "reg '\\var_16' is assigned in a continuous assignment" 1
+logger -expect warning "reg '\\var_17' is assigned in a continuous assignment" 1
+logger -expect warning "reg '\\var_18' is assigned in a continuous assignment" 1
+logger -expect warning "reg '\\var_19' is assigned in a continuous assignment" 1
+
+read_verilog -sv typedef_initial_and_assign.sv
+hierarchy; proc; opt
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all \ No newline at end of file
diff --git a/tests/svtypes/typedef_memory.ys b/tests/svtypes/typedef_memory.ys
index 93cf47bbe..d47ee9929 100644
--- a/tests/svtypes/typedef_memory.ys
+++ b/tests/svtypes/typedef_memory.ys
@@ -1,3 +1,3 @@
read_verilog -sv typedef_memory.sv
prep -top top
-select -assert-count 1 t:$mem r:SIZE=16 %i r:WIDTH=4 %i
+select -assert-count 1 t:$mem_v2 r:SIZE=16 %i r:WIDTH=4 %i
diff --git a/tests/svtypes/typedef_memory_2.ys b/tests/svtypes/typedef_memory_2.ys
index 854e554f3..bfebd05fc 100644
--- a/tests/svtypes/typedef_memory_2.ys
+++ b/tests/svtypes/typedef_memory_2.ys
@@ -1,4 +1,4 @@
read_verilog -sv typedef_memory_2.sv
prep -top top
dump
-select -assert-count 1 t:$mem r:SIZE=16 %i r:WIDTH=4 %i
+select -assert-count 1 t:$mem_v2 r:SIZE=16 %i r:WIDTH=4 %i
diff --git a/tests/svtypes/typedef_scopes.sv b/tests/svtypes/typedef_scopes.sv
index 5507d84f2..9a898fac8 100644
--- a/tests/svtypes/typedef_scopes.sv
+++ b/tests/svtypes/typedef_scopes.sv
@@ -4,6 +4,7 @@ typedef enum logic {s0, s1} outer_enum_t;
module top;
+ // globals are inherited
outer_uint4_t u4_i = 8'hA5;
outer_enum_t enum4_i = s0;
always @(*) assert(u4_i == 4'h5);
@@ -17,13 +18,22 @@ module top;
always @(*) assert(inner_enum1 == 3'h3);
if (1) begin: genblock
+ // type declarations in child scopes shadow their parents
typedef logic [7:0] inner_type;
parameter inner_type inner_const = 8'hA5;
typedef enum logic [2:0] {s5=5, s6, s7} inner_enum_t;
+
inner_type inner_gb_i = inner_const; //8'hA5;
inner_enum_t inner_gb_enum1 = s7;
always @(*) assert(inner_gb_i == 8'hA5);
always @(*) assert(inner_gb_enum1 == 3'h7);
+
+ // check that copying of struct member types works over multiple type scopes
+ typedef struct packed {
+ outer_uint4_t x;
+ } mystruct_t;
+ mystruct_t mystruct;
+ always @(*) assert($bits(mystruct) == 4);
end
inner_type inner_i2 = 8'h42;
diff --git a/tests/techmap/bug2759.ys b/tests/techmap/bug2759.ys
new file mode 100644
index 000000000..05699bef8
--- /dev/null
+++ b/tests/techmap/bug2759.ys
@@ -0,0 +1,14 @@
+read_verilog -specify <<EOT
+(* abc9_box, whitebox *)
+module box(input [1:0] i, output o);
+specify
+(i *> o) = 1;
+endspecify
+assign o = ^i;
+endmodule
+
+module top(input [1:0] i, output o);
+box i1(i, o);
+endmodule
+EOT
+abc9 -lut 4
diff --git a/tests/techmap/bug2972.ys b/tests/techmap/bug2972.ys
new file mode 100644
index 000000000..8ae895f56
--- /dev/null
+++ b/tests/techmap/bug2972.ys
@@ -0,0 +1,20 @@
+read_verilog -specify <<EOT
+(* abc9_box, blackbox*)
+module box(input clk, d, output reg q, output do);
+parameter P = 0;
+always @(posedge clk)
+ q <= d;
+assign do = d;
+specify
+ (posedge clk => (q : d)) = 1;
+ (d => do) = 1;
+endspecify
+endmodule
+
+module top(input clk, d, output q);
+box i1(clk, d, q);
+endmodule
+EOT
+hierarchy
+abc9 -lut 4
+abc9 -lut 4
diff --git a/tests/techmap/dfflegalize_adff.ys b/tests/techmap/dfflegalize_adff.ys
index 135ae0ab7..fc579e7d6 100644
--- a/tests/techmap/dfflegalize_adff.ys
+++ b/tests/techmap/dfflegalize_adff.ys
@@ -39,6 +39,8 @@ design -save orig
flatten
equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP0_ x
equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP0P_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFF_PP_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFFE_PPP_ x
equiv_opt -assert -multiclock dfflegalize -cell $_DFFSR_PPP_ x
equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_PPPP_ x
@@ -73,6 +75,36 @@ select -assert-count 14 t:$_DFFE_PP0P_
select -assert-none t:$_DFFE_PP0P_ t:$_NOT_ top/* %% %n t:* %i
+# Convert everything to ALDFFs.
+
+design -load orig
+dfflegalize -cell $_ALDFF_PP_ x
+
+select -assert-count 2 adff0/t:$_NOT_
+select -assert-count 2 adff1/t:$_NOT_
+select -assert-count 2 adffe0/t:$_NOT_
+select -assert-count 2 adffe1/t:$_NOT_
+select -assert-count 0 adff0/t:$_MUX_
+select -assert-count 0 adff1/t:$_MUX_
+select -assert-count 4 adffe0/t:$_MUX_
+select -assert-count 4 adffe1/t:$_MUX_
+select -assert-count 14 t:$_ALDFF_PP_
+select -assert-none t:$_ALDFF_PP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to ALDFFEs.
+
+design -load orig
+dfflegalize -cell $_ALDFFE_PPP_ x
+
+select -assert-count 2 adff0/t:$_NOT_
+select -assert-count 2 adff1/t:$_NOT_
+select -assert-count 3 adffe0/t:$_NOT_
+select -assert-count 3 adffe1/t:$_NOT_
+select -assert-count 14 t:$_ALDFFE_PPP_
+select -assert-none t:$_ALDFFE_PPP_ t:$_NOT_ top/* %% %n t:* %i
+
+
# Convert everything to DFFSRs.
design -load orig
diff --git a/tests/techmap/dfflegalize_adff_init.ys b/tests/techmap/dfflegalize_adff_init.ys
index 7764e15a5..25ed59307 100644
--- a/tests/techmap/dfflegalize_adff_init.ys
+++ b/tests/techmap/dfflegalize_adff_init.ys
@@ -45,6 +45,10 @@ equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP0P_ 0 -cell $_DLATCH_P_
equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP0P_ 1 -cell $_DLATCH_P_ 1
equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP1P_ 0 -cell $_DLATCH_P_ 1
equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP1P_ 1 -cell $_DLATCH_P_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFF_PP_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFF_PP_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFFE_PPP_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFFE_PPP_ 1
equiv_opt -assert -multiclock dfflegalize -cell $_DFFSR_PPP_ 0
equiv_opt -assert -multiclock dfflegalize -cell $_DFFSR_PPP_ 1
equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_PPPP_ 0
@@ -144,9 +148,9 @@ design -load orig
dfflegalize -cell $_DFFE_PP0P_ 0 -cell $_DLATCH_P_ 1
select -assert-count 2 adff0/t:$_NOT_
-select -assert-count 16 adff1/t:$_NOT_
+select -assert-count 13 adff1/t:$_NOT_
select -assert-count 3 adffe0/t:$_NOT_
-select -assert-count 22 adffe1/t:$_NOT_
+select -assert-count 18 adffe1/t:$_NOT_
select -assert-count 0 adff0/t:$_MUX_
select -assert-count 3 adff1/t:$_MUX_
select -assert-count 0 adffe0/t:$_MUX_
@@ -164,9 +168,9 @@ select -assert-none t:$_DFFE_PP0P_ t:$_DLATCH_P_ t:$_MUX_ t:$_NOT_ top/* %% %n t
design -load orig
dfflegalize -cell $_DFFE_PP0P_ 1 -cell $_DLATCH_P_ 1
-select -assert-count 16 adff0/t:$_NOT_
+select -assert-count 13 adff0/t:$_NOT_
select -assert-count 8 adff1/t:$_NOT_
-select -assert-count 22 adffe0/t:$_NOT_
+select -assert-count 18 adffe0/t:$_NOT_
select -assert-count 11 adffe1/t:$_NOT_
select -assert-count 3 adff0/t:$_MUX_
select -assert-count 0 adff1/t:$_MUX_
@@ -185,31 +189,27 @@ select -assert-none t:$_DFFE_PP0P_ t:$_DLATCH_P_ t:$_MUX_ t:$_NOT_ top/* %% %n t
design -load orig
dfflegalize -cell $_DFFE_PP1P_ 0 -cell $_DLATCH_P_ 1
-select -assert-count 16 adff0/t:$_NOT_
+select -assert-count 10 adff0/t:$_NOT_
select -assert-count 2 adff1/t:$_NOT_
-select -assert-count 22 adffe0/t:$_NOT_
+select -assert-count 14 adffe0/t:$_NOT_
select -assert-count 3 adffe1/t:$_NOT_
select -assert-count 3 adff0/t:$_MUX_
select -assert-count 0 adff1/t:$_MUX_
select -assert-count 4 adffe0/t:$_MUX_
select -assert-count 0 adffe1/t:$_MUX_
-select -assert-count 6 adff0/t:$_DFFE_PP1P_
+select -assert-count 9 adff0/t:$_DFFE_PP1P_
select -assert-count 3 adff1/t:$_DFFE_PP1P_
-select -assert-count 8 adffe0/t:$_DFFE_PP1P_
+select -assert-count 12 adffe0/t:$_DFFE_PP1P_
select -assert-count 4 adffe1/t:$_DFFE_PP1P_
-select -assert-count 3 adff0/t:$_DLATCH_P_
-select -assert-count 0 adff1/t:$_DLATCH_P_
-select -assert-count 4 adffe0/t:$_DLATCH_P_
-select -assert-count 0 adffe1/t:$_DLATCH_P_
-select -assert-none t:$_DFFE_PP1P_ t:$_DLATCH_P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+select -assert-none t:$_DFFE_PP1P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
design -load orig
dfflegalize -cell $_DFFE_PP1P_ 1 -cell $_DLATCH_P_ 1
select -assert-count 8 adff0/t:$_NOT_
-select -assert-count 16 adff1/t:$_NOT_
+select -assert-count 13 adff1/t:$_NOT_
select -assert-count 11 adffe0/t:$_NOT_
-select -assert-count 22 adffe1/t:$_NOT_
+select -assert-count 18 adffe1/t:$_NOT_
select -assert-count 0 adff0/t:$_MUX_
select -assert-count 3 adff1/t:$_MUX_
select -assert-count 0 adffe0/t:$_MUX_
@@ -225,6 +225,60 @@ select -assert-count 4 adffe1/t:$_DLATCH_P_
select -assert-none t:$_DFFE_PP1P_ t:$_DLATCH_P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+# Convert everything to ALDFFs.
+
+design -load orig
+dfflegalize -cell $_ALDFF_PP_ 0
+
+select -assert-count 2 adff0/t:$_NOT_
+select -assert-count 2 adff1/t:$_NOT_
+select -assert-count 2 adffe0/t:$_NOT_
+select -assert-count 2 adffe1/t:$_NOT_
+select -assert-count 0 adff0/t:$_MUX_
+select -assert-count 0 adff1/t:$_MUX_
+select -assert-count 4 adffe0/t:$_MUX_
+select -assert-count 4 adffe1/t:$_MUX_
+select -assert-count 14 t:$_ALDFF_PP_
+select -assert-none t:$_ALDFF_PP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_ALDFF_PP_ 1
+
+select -assert-count 8 adff0/t:$_NOT_
+select -assert-count 8 adff1/t:$_NOT_
+select -assert-count 10 adffe0/t:$_NOT_
+select -assert-count 10 adffe1/t:$_NOT_
+select -assert-count 0 adff0/t:$_MUX_
+select -assert-count 0 adff1/t:$_MUX_
+select -assert-count 4 adffe0/t:$_MUX_
+select -assert-count 4 adffe1/t:$_MUX_
+select -assert-count 14 t:$_ALDFF_PP_
+select -assert-none t:$_ALDFF_PP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to ALDFFEs.
+
+design -load orig
+dfflegalize -cell $_ALDFFE_PPP_ 0
+
+select -assert-count 2 adff0/t:$_NOT_
+select -assert-count 2 adff1/t:$_NOT_
+select -assert-count 3 adffe0/t:$_NOT_
+select -assert-count 3 adffe1/t:$_NOT_
+select -assert-count 14 t:$_ALDFFE_PPP_
+select -assert-none t:$_ALDFFE_PPP_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_ALDFFE_PPP_ 1
+
+select -assert-count 8 adff0/t:$_NOT_
+select -assert-count 8 adff1/t:$_NOT_
+select -assert-count 11 adffe0/t:$_NOT_
+select -assert-count 11 adffe1/t:$_NOT_
+select -assert-count 14 t:$_ALDFFE_PPP_
+select -assert-none t:$_ALDFFE_PPP_ t:$_NOT_ top/* %% %n t:* %i
+
+
# Convert everything to DFFSRs.
design -load orig
diff --git a/tests/techmap/dfflegalize_adlatch_init.ys b/tests/techmap/dfflegalize_adlatch_init.ys
index 7b22ea0c0..a55082d1d 100644
--- a/tests/techmap/dfflegalize_adlatch_init.ys
+++ b/tests/techmap/dfflegalize_adlatch_init.ys
@@ -45,7 +45,7 @@ select -assert-none t:$_DLATCH_PP0_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
design -load orig
dfflegalize -cell $_DLATCH_PP0_ 1
-select -assert-count 16 adlatch0/t:$_NOT_
+select -assert-count 13 adlatch0/t:$_NOT_
select -assert-count 8 adlatch1/t:$_NOT_
select -assert-count 3 adlatch0/t:$_MUX_
select -assert-count 0 adlatch1/t:$_MUX_
@@ -68,7 +68,7 @@ design -load orig
dfflegalize -cell $_DLATCH_PP1_ 1
select -assert-count 8 adlatch0/t:$_NOT_
-select -assert-count 16 adlatch1/t:$_NOT_
+select -assert-count 13 adlatch1/t:$_NOT_
select -assert-count 0 adlatch0/t:$_MUX_
select -assert-count 3 adlatch1/t:$_MUX_
select -assert-count 3 adlatch0/t:$_DLATCH_PP1_
diff --git a/tests/techmap/dfflegalize_aldff.ys b/tests/techmap/dfflegalize_aldff.ys
new file mode 100644
index 000000000..1ee9e3af6
--- /dev/null
+++ b/tests/techmap/dfflegalize_aldff.ys
@@ -0,0 +1,92 @@
+read_verilog -icells <<EOT
+
+module aldff(input C, L, AD, D, output [2:0] Q);
+$_ALDFF_PP_ ff0 (.C(C), .L(L), .AD(AD), .D(D), .Q(Q[0]));
+$_ALDFF_PN_ ff1 (.C(C), .L(L), .AD(AD), .D(D), .Q(Q[1]));
+$_ALDFF_NP_ ff2 (.C(C), .L(L), .AD(AD), .D(D), .Q(Q[2]));
+endmodule
+
+module aldffe(input C, E, L, AD, D, output [3:0] Q);
+$_ALDFFE_PPP_ ff0 (.C(C), .L(L), .AD(AD), .E(E), .D(D), .Q(Q[0]));
+$_ALDFFE_PPN_ ff1 (.C(C), .L(L), .AD(AD), .E(E), .D(D), .Q(Q[1]));
+$_ALDFFE_PNP_ ff2 (.C(C), .L(L), .AD(AD), .E(E), .D(D), .Q(Q[2]));
+$_ALDFFE_NPP_ ff3 (.C(C), .L(L), .AD(AD), .E(E), .D(D), .Q(Q[3]));
+endmodule
+
+module top(input C, E, L, AD, D, output [6:0] Q);
+aldff aldff_(.C(C), .L(L), .AD(AD), .D(D), .Q(Q[2:0]));
+aldffe aldffe_(.C(C), .L(L), .AD(AD), .E(E), .D(D), .Q(Q[6:3]));
+endmodule
+
+EOT
+
+design -save orig
+flatten
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFF_PP_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFFE_PPP_ x
+#equiv_opt -assert -multiclock dfflegalize -cell $_DFFSR_PPP_ x
+#equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_PPPP_ x
+
+
+# Convert everything to ALDFFs.
+
+design -load orig
+dfflegalize -cell $_ALDFF_PP_ x
+
+select -assert-count 2 aldff/t:$_NOT_
+select -assert-count 2 aldffe/t:$_NOT_
+select -assert-count 0 aldff/t:$_MUX_
+select -assert-count 4 aldffe/t:$_MUX_
+select -assert-count 7 t:$_ALDFF_PP_
+select -assert-none t:$_ALDFF_PP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to ALDFFEs.
+
+design -load orig
+dfflegalize -cell $_ALDFFE_PPP_ x
+
+select -assert-count 2 aldff/t:$_NOT_
+select -assert-count 3 aldffe/t:$_NOT_
+select -assert-count 7 t:$_ALDFFE_PPP_
+select -assert-none t:$_ALDFFE_PPP_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFSRs.
+
+design -load orig
+dfflegalize -cell $_DFFSR_PPP_ x
+
+select -assert-count 2 aldff/t:$_AND_
+select -assert-count 3 aldffe/t:$_AND_
+select -assert-count 2 aldff/t:$_ANDNOT_
+select -assert-count 3 aldffe/t:$_ANDNOT_
+select -assert-count 1 aldff/t:$_OR_
+select -assert-count 1 aldffe/t:$_OR_
+select -assert-count 1 aldff/t:$_ORNOT_
+select -assert-count 1 aldffe/t:$_ORNOT_
+select -assert-count 3 aldff/t:$_NOT_
+select -assert-count 3 aldffe/t:$_NOT_
+select -assert-count 0 aldff/t:$_MUX_
+select -assert-count 4 aldffe/t:$_MUX_
+select -assert-count 7 t:$_DFFSR_PPP_
+select -assert-none t:$_DFFSR_PPP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ t:$_ORNOT_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFSREs.
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ x
+
+select -assert-count 2 aldff/t:$_AND_
+select -assert-count 3 aldffe/t:$_AND_
+select -assert-count 2 aldff/t:$_ANDNOT_
+select -assert-count 3 aldffe/t:$_ANDNOT_
+select -assert-count 1 aldff/t:$_OR_
+select -assert-count 1 aldffe/t:$_OR_
+select -assert-count 1 aldff/t:$_ORNOT_
+select -assert-count 1 aldffe/t:$_ORNOT_
+select -assert-count 3 aldff/t:$_NOT_
+select -assert-count 4 aldffe/t:$_NOT_
+select -assert-count 7 t:$_DFFSRE_PPPP_
+select -assert-none t:$_DFFSRE_PPPP_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ t:$_ORNOT_ top/* %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_aldff_init.ys b/tests/techmap/dfflegalize_aldff_init.ys
new file mode 100644
index 000000000..f4db8dd32
--- /dev/null
+++ b/tests/techmap/dfflegalize_aldff_init.ys
@@ -0,0 +1,148 @@
+read_verilog -icells <<EOT
+
+module aldff(input C, L, AD, D, (* init = 3'b000 *) output [2:0] Q);
+$_ALDFF_PP_ ff0 (.C(C), .L(L), .AD(AD), .D(D), .Q(Q[0]));
+$_ALDFF_PN_ ff1 (.C(C), .L(L), .AD(AD), .D(D), .Q(Q[1]));
+$_ALDFF_NP_ ff2 (.C(C), .L(L), .AD(AD), .D(D), .Q(Q[2]));
+endmodule
+
+module aldffe(input C, E, L, AD, D, (* init = 4'b0000 *) output [3:0] Q);
+$_ALDFFE_PPP_ ff0 (.C(C), .L(L), .AD(AD), .E(E), .D(D), .Q(Q[0]));
+$_ALDFFE_PPN_ ff1 (.C(C), .L(L), .AD(AD), .E(E), .D(D), .Q(Q[1]));
+$_ALDFFE_PNP_ ff2 (.C(C), .L(L), .AD(AD), .E(E), .D(D), .Q(Q[2]));
+$_ALDFFE_NPP_ ff3 (.C(C), .L(L), .AD(AD), .E(E), .D(D), .Q(Q[3]));
+endmodule
+
+module top(input C, E, L, AD, D, output [6:0] Q);
+aldff aldff_(.C(C), .L(L), .AD(AD), .D(D), .Q(Q[2:0]));
+aldffe aldffe_(.C(C), .L(L), .AD(AD), .E(E), .D(D), .Q(Q[6:3]));
+endmodule
+
+EOT
+
+design -save orig
+flatten
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFF_PP_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFF_PP_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFFE_PPP_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFFE_PPP_ 1
+#equiv_opt -assert -multiclock dfflegalize -cell $_DFFSR_PPP_ 0
+#equiv_opt -assert -multiclock dfflegalize -cell $_DFFSR_PPP_ 1
+#equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_PPPP_ 0
+#equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_PPPP_ 1
+
+
+# Convert everything to ALDFFs.
+
+design -load orig
+dfflegalize -cell $_ALDFF_PP_ 0
+
+select -assert-count 2 aldff/t:$_NOT_
+select -assert-count 2 aldffe/t:$_NOT_
+select -assert-count 0 aldff/t:$_MUX_
+select -assert-count 4 aldffe/t:$_MUX_
+select -assert-count 7 t:$_ALDFF_PP_
+select -assert-none t:$_ALDFF_PP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_ALDFF_PP_ 1
+
+select -assert-count 11 aldff/t:$_NOT_
+select -assert-count 14 aldffe/t:$_NOT_
+select -assert-count 0 aldff/t:$_MUX_
+select -assert-count 4 aldffe/t:$_MUX_
+select -assert-count 7 t:$_ALDFF_PP_
+select -assert-none t:$_ALDFF_PP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to ALDFFEs.
+
+design -load orig
+dfflegalize -cell $_ALDFFE_PPP_ 0
+
+select -assert-count 2 aldff/t:$_NOT_
+select -assert-count 3 aldffe/t:$_NOT_
+select -assert-count 7 t:$_ALDFFE_PPP_
+select -assert-none t:$_ALDFFE_PPP_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_ALDFFE_PPP_ 1
+
+select -assert-count 11 aldff/t:$_NOT_
+select -assert-count 15 aldffe/t:$_NOT_
+select -assert-count 7 t:$_ALDFFE_PPP_
+select -assert-none t:$_ALDFFE_PPP_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFSRs.
+
+design -load orig
+dfflegalize -cell $_DFFSR_PPP_ 0
+
+select -assert-count 2 aldff/t:$_AND_
+select -assert-count 3 aldffe/t:$_AND_
+select -assert-count 2 aldff/t:$_ANDNOT_
+select -assert-count 3 aldffe/t:$_ANDNOT_
+select -assert-count 1 aldff/t:$_OR_
+select -assert-count 1 aldffe/t:$_OR_
+select -assert-count 1 aldff/t:$_ORNOT_
+select -assert-count 1 aldffe/t:$_ORNOT_
+select -assert-count 3 aldff/t:$_NOT_
+select -assert-count 3 aldffe/t:$_NOT_
+select -assert-count 0 aldff/t:$_MUX_
+select -assert-count 4 aldffe/t:$_MUX_
+select -assert-count 7 t:$_DFFSR_PPP_
+select -assert-none t:$_DFFSR_PPP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ t:$_ORNOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFSR_PPP_ 1
+
+select -assert-count 2 aldff/t:$_AND_
+select -assert-count 3 aldffe/t:$_AND_
+select -assert-count 2 aldff/t:$_ANDNOT_
+select -assert-count 3 aldffe/t:$_ANDNOT_
+select -assert-count 1 aldff/t:$_OR_
+select -assert-count 1 aldffe/t:$_OR_
+select -assert-count 1 aldff/t:$_ORNOT_
+select -assert-count 1 aldffe/t:$_ORNOT_
+select -assert-count 12 aldff/t:$_NOT_
+select -assert-count 15 aldffe/t:$_NOT_
+select -assert-count 0 aldff/t:$_MUX_
+select -assert-count 4 aldffe/t:$_MUX_
+select -assert-count 7 t:$_DFFSR_PPP_
+select -assert-none t:$_DFFSR_PPP_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ t:$_ORNOT_ top/* %% %n t:* %i
+
+
+# Convert everything to DFFSREs.
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ 0
+
+select -assert-count 2 aldff/t:$_AND_
+select -assert-count 3 aldffe/t:$_AND_
+select -assert-count 2 aldff/t:$_ANDNOT_
+select -assert-count 3 aldffe/t:$_ANDNOT_
+select -assert-count 1 aldff/t:$_OR_
+select -assert-count 1 aldffe/t:$_OR_
+select -assert-count 1 aldff/t:$_ORNOT_
+select -assert-count 1 aldffe/t:$_ORNOT_
+select -assert-count 3 aldff/t:$_NOT_
+select -assert-count 4 aldffe/t:$_NOT_
+select -assert-count 7 t:$_DFFSRE_PPPP_
+select -assert-none t:$_DFFSRE_PPPP_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ t:$_ORNOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_DFFSRE_PPPP_ 1
+
+select -assert-count 2 aldff/t:$_AND_
+select -assert-count 3 aldffe/t:$_AND_
+select -assert-count 2 aldff/t:$_ANDNOT_
+select -assert-count 3 aldffe/t:$_ANDNOT_
+select -assert-count 1 aldff/t:$_OR_
+select -assert-count 1 aldffe/t:$_OR_
+select -assert-count 1 aldff/t:$_ORNOT_
+select -assert-count 1 aldffe/t:$_ORNOT_
+select -assert-count 12 aldff/t:$_NOT_
+select -assert-count 16 aldffe/t:$_NOT_
+select -assert-count 7 t:$_DFFSRE_PPPP_
+select -assert-none t:$_DFFSRE_PPPP_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_OR_ t:$_ORNOT_ top/* %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_dff.ys b/tests/techmap/dfflegalize_dff.ys
index 63ab47865..374289678 100644
--- a/tests/techmap/dfflegalize_dff.ys
+++ b/tests/techmap/dfflegalize_dff.ys
@@ -70,6 +70,8 @@ equiv_opt -assert -multiclock dfflegalize -cell $_DFF_P_ x
equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP_ x
equiv_opt -assert -multiclock dfflegalize -cell $_DFF_PP0_ x
equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP0P_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFF_PP_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFFE_PPP_ x
equiv_opt -assert -multiclock dfflegalize -cell $_DFFSR_PPP_ x
equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_PPPP_ x
equiv_opt -assert -multiclock dfflegalize -cell $_SDFF_PP0_ x
@@ -176,6 +178,56 @@ select -assert-count 27 t:$_DFFE_PP0P_
select -assert-none t:$_DFFE_PP0P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+# Convert everything to ALDFFs.
+
+design -load orig
+dfflegalize -cell $_ALDFF_PP_ x
+
+select -assert-count 1 dff/t:$_NOT_
+select -assert-count 1 dffe/t:$_NOT_
+select -assert-count 1 sdff0/t:$_NOT_
+select -assert-count 1 sdff1/t:$_NOT_
+select -assert-count 1 sdffe0/t:$_NOT_
+select -assert-count 1 sdffe1/t:$_NOT_
+select -assert-count 1 sdffce0/t:$_NOT_
+select -assert-count 1 sdffce1/t:$_NOT_
+select -assert-count 0 dff/t:$_MUX_
+select -assert-count 3 dffe/t:$_MUX_
+select -assert-count 3 sdff0/t:$_MUX_
+select -assert-count 3 sdff1/t:$_MUX_
+select -assert-count 8 sdffe0/t:$_MUX_
+select -assert-count 8 sdffe1/t:$_MUX_
+select -assert-count 8 sdffce0/t:$_MUX_
+select -assert-count 8 sdffce1/t:$_MUX_
+select -assert-count 27 t:$_ALDFF_PP_
+select -assert-none t:$_ALDFF_PP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to ALDFFEs.
+
+design -load orig
+dfflegalize -cell $_ALDFFE_PPP_ x
+
+select -assert-count 1 dff/t:$_NOT_
+select -assert-count 2 dffe/t:$_NOT_
+select -assert-count 1 sdff0/t:$_NOT_
+select -assert-count 1 sdff1/t:$_NOT_
+select -assert-count 1 sdffe0/t:$_NOT_
+select -assert-count 1 sdffe1/t:$_NOT_
+select -assert-count 2 sdffce0/t:$_NOT_
+select -assert-count 2 sdffce1/t:$_NOT_
+select -assert-count 0 dff/t:$_MUX_
+select -assert-count 0 dffe/t:$_MUX_
+select -assert-count 3 sdff0/t:$_MUX_
+select -assert-count 3 sdff1/t:$_MUX_
+select -assert-count 8 sdffe0/t:$_MUX_
+select -assert-count 8 sdffe1/t:$_MUX_
+select -assert-count 4 sdffce0/t:$_MUX_
+select -assert-count 4 sdffce1/t:$_MUX_
+select -assert-count 27 t:$_ALDFFE_PPP_
+select -assert-none t:$_ALDFFE_PPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
# Convert everything to DFFSRs.
design -load orig
@@ -237,25 +289,18 @@ select -assert-count 2 sdff0/t:$_NOT_
select -assert-count 8 sdff1/t:$_NOT_
select -assert-count 2 sdffe0/t:$_NOT_
select -assert-count 10 sdffe1/t:$_NOT_
-select -assert-count 2 sdffce0/t:$_NOT_
-select -assert-count 10 sdffce1/t:$_NOT_
+select -assert-count 1 sdffce0/t:$_NOT_
+select -assert-count 1 sdffce1/t:$_NOT_
select -assert-count 0 dff/t:$_MUX_
select -assert-count 3 dffe/t:$_MUX_
select -assert-count 0 sdff0/t:$_MUX_
select -assert-count 0 sdff1/t:$_MUX_
select -assert-count 4 sdffe0/t:$_MUX_
select -assert-count 4 sdffe1/t:$_MUX_
-select -assert-count 4 sdffce0/t:$_MUX_
-select -assert-count 4 sdffce1/t:$_MUX_
-select -assert-count 0 t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ %% sdffce0/* sdffce1/* %u %n %i
-select -assert-count 2 sdffce0/t:$_AND_
-select -assert-count 2 sdffce1/t:$_AND_
-select -assert-count 1 sdffce0/t:$_ORNOT_
-select -assert-count 1 sdffce1/t:$_ORNOT_
-select -assert-count 1 sdffce0/t:$_ANDNOT_
-select -assert-count 1 sdffce1/t:$_ANDNOT_
+select -assert-count 8 sdffce0/t:$_MUX_
+select -assert-count 8 sdffce1/t:$_MUX_
select -assert-count 27 t:$_SDFF_PP0_
-select -assert-none t:$_SDFF_PP0_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
+select -assert-none t:$_SDFF_PP0_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
# Convert everything to SDFFEs.
diff --git a/tests/techmap/dfflegalize_dff_init.ys b/tests/techmap/dfflegalize_dff_init.ys
index 741ac39d0..a170249c7 100644
--- a/tests/techmap/dfflegalize_dff_init.ys
+++ b/tests/techmap/dfflegalize_dff_init.ys
@@ -78,6 +78,10 @@ equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP0P_ 0
equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP0P_ 1
equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP1P_ 0
equiv_opt -assert -multiclock dfflegalize -cell $_DFFE_PP1P_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFF_PP_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFF_PP_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFFE_PPP_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFFE_PPP_ 1
equiv_opt -assert -multiclock dfflegalize -cell $_DFFSR_PPP_ 0
equiv_opt -assert -multiclock dfflegalize -cell $_DFFSR_PPP_ 1
equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_PPPP_ 0
@@ -371,6 +375,100 @@ select -assert-count 27 t:$_DFFE_PP1P_
select -assert-none t:$_DFFE_PP1P_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+# Convert everything to ALDFFs.
+
+design -load orig
+dfflegalize -cell $_ALDFF_PP_ 0
+
+select -assert-count 1 dff/t:$_NOT_
+select -assert-count 1 dffe/t:$_NOT_
+select -assert-count 1 sdff0/t:$_NOT_
+select -assert-count 1 sdff1/t:$_NOT_
+select -assert-count 1 sdffe0/t:$_NOT_
+select -assert-count 1 sdffe1/t:$_NOT_
+select -assert-count 1 sdffce0/t:$_NOT_
+select -assert-count 1 sdffce1/t:$_NOT_
+select -assert-count 0 dff/t:$_MUX_
+select -assert-count 3 dffe/t:$_MUX_
+select -assert-count 3 sdff0/t:$_MUX_
+select -assert-count 3 sdff1/t:$_MUX_
+select -assert-count 8 sdffe0/t:$_MUX_
+select -assert-count 8 sdffe1/t:$_MUX_
+select -assert-count 8 sdffce0/t:$_MUX_
+select -assert-count 8 sdffce1/t:$_MUX_
+select -assert-count 27 t:$_ALDFF_PP_
+select -assert-none t:$_ALDFF_PP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_ALDFF_PP_ 1
+
+select -assert-count 5 dff/t:$_NOT_
+select -assert-count 7 dffe/t:$_NOT_
+select -assert-count 7 sdff0/t:$_NOT_
+select -assert-count 7 sdff1/t:$_NOT_
+select -assert-count 9 sdffe0/t:$_NOT_
+select -assert-count 9 sdffe1/t:$_NOT_
+select -assert-count 9 sdffce0/t:$_NOT_
+select -assert-count 9 sdffce1/t:$_NOT_
+select -assert-count 0 dff/t:$_MUX_
+select -assert-count 3 dffe/t:$_MUX_
+select -assert-count 3 sdff0/t:$_MUX_
+select -assert-count 3 sdff1/t:$_MUX_
+select -assert-count 8 sdffe0/t:$_MUX_
+select -assert-count 8 sdffe1/t:$_MUX_
+select -assert-count 8 sdffce0/t:$_MUX_
+select -assert-count 8 sdffce1/t:$_MUX_
+select -assert-count 27 t:$_ALDFF_PP_
+select -assert-none t:$_ALDFF_PP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
+# Convert everything to ALDFFEs.
+
+design -load orig
+dfflegalize -cell $_ALDFFE_PPP_ 0
+
+select -assert-count 1 dff/t:$_NOT_
+select -assert-count 2 dffe/t:$_NOT_
+select -assert-count 1 sdff0/t:$_NOT_
+select -assert-count 1 sdff1/t:$_NOT_
+select -assert-count 1 sdffe0/t:$_NOT_
+select -assert-count 1 sdffe1/t:$_NOT_
+select -assert-count 2 sdffce0/t:$_NOT_
+select -assert-count 2 sdffce1/t:$_NOT_
+select -assert-count 0 dff/t:$_MUX_
+select -assert-count 0 dffe/t:$_MUX_
+select -assert-count 3 sdff0/t:$_MUX_
+select -assert-count 3 sdff1/t:$_MUX_
+select -assert-count 8 sdffe0/t:$_MUX_
+select -assert-count 8 sdffe1/t:$_MUX_
+select -assert-count 4 sdffce0/t:$_MUX_
+select -assert-count 4 sdffce1/t:$_MUX_
+select -assert-count 27 t:$_ALDFFE_PPP_
+select -assert-none t:$_ALDFFE_PPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_ALDFFE_PPP_ 1
+
+select -assert-count 5 dff/t:$_NOT_
+select -assert-count 8 dffe/t:$_NOT_
+select -assert-count 7 sdff0/t:$_NOT_
+select -assert-count 7 sdff1/t:$_NOT_
+select -assert-count 9 sdffe0/t:$_NOT_
+select -assert-count 9 sdffe1/t:$_NOT_
+select -assert-count 10 sdffce0/t:$_NOT_
+select -assert-count 10 sdffce1/t:$_NOT_
+select -assert-count 0 dff/t:$_MUX_
+select -assert-count 0 dffe/t:$_MUX_
+select -assert-count 3 sdff0/t:$_MUX_
+select -assert-count 3 sdff1/t:$_MUX_
+select -assert-count 8 sdffe0/t:$_MUX_
+select -assert-count 8 sdffe1/t:$_MUX_
+select -assert-count 4 sdffce0/t:$_MUX_
+select -assert-count 4 sdffce1/t:$_MUX_
+select -assert-count 27 t:$_ALDFFE_PPP_
+select -assert-none t:$_ALDFFE_PPP_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
+
+
# Convert everything to DFFSRs.
design -load orig
@@ -476,7 +574,7 @@ select -assert-count 2 sdff0/t:$_NOT_
select -assert-count 1 sdff1/t:$_NOT_
select -assert-count 2 sdffe0/t:$_NOT_
select -assert-count 1 sdffe1/t:$_NOT_
-select -assert-count 2 sdffce0/t:$_NOT_
+select -assert-count 1 sdffce0/t:$_NOT_
select -assert-count 1 sdffce1/t:$_NOT_
select -assert-count 0 dff/t:$_MUX_
select -assert-count 3 dffe/t:$_MUX_
@@ -484,14 +582,10 @@ select -assert-count 0 sdff0/t:$_MUX_
select -assert-count 3 sdff1/t:$_MUX_
select -assert-count 4 sdffe0/t:$_MUX_
select -assert-count 8 sdffe1/t:$_MUX_
-select -assert-count 4 sdffce0/t:$_MUX_
+select -assert-count 8 sdffce0/t:$_MUX_
select -assert-count 8 sdffce1/t:$_MUX_
-select -assert-count 0 t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ %% sdffce0/* %n %i
-select -assert-count 2 sdffce0/t:$_AND_
-select -assert-count 1 sdffce0/t:$_ORNOT_
-select -assert-count 1 sdffce0/t:$_ANDNOT_
select -assert-count 27 t:$_SDFF_PP0_
-select -assert-none t:$_SDFF_PP0_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
+select -assert-none t:$_SDFF_PP0_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
design -load orig
dfflegalize -cell $_SDFF_PP0_ 1
@@ -503,7 +597,7 @@ select -assert-count 8 sdff1/t:$_NOT_
select -assert-count 9 sdffe0/t:$_NOT_
select -assert-count 10 sdffe1/t:$_NOT_
select -assert-count 9 sdffce0/t:$_NOT_
-select -assert-count 10 sdffce1/t:$_NOT_
+select -assert-count 9 sdffce1/t:$_NOT_
select -assert-count 0 dff/t:$_MUX_
select -assert-count 3 dffe/t:$_MUX_
select -assert-count 3 sdff0/t:$_MUX_
@@ -511,13 +605,9 @@ select -assert-count 0 sdff1/t:$_MUX_
select -assert-count 8 sdffe0/t:$_MUX_
select -assert-count 4 sdffe1/t:$_MUX_
select -assert-count 8 sdffce0/t:$_MUX_
-select -assert-count 4 sdffce1/t:$_MUX_
-select -assert-count 0 t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ %% sdffce1/* %n %i
-select -assert-count 2 sdffce1/t:$_AND_
-select -assert-count 1 sdffce1/t:$_ORNOT_
-select -assert-count 1 sdffce1/t:$_ANDNOT_
+select -assert-count 8 sdffce1/t:$_MUX_
select -assert-count 27 t:$_SDFF_PP0_
-select -assert-none t:$_SDFF_PP0_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
+select -assert-none t:$_SDFF_PP0_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
design -load orig
dfflegalize -cell $_SDFF_PP1_ 0
@@ -529,7 +619,7 @@ select -assert-count 2 sdff1/t:$_NOT_
select -assert-count 1 sdffe0/t:$_NOT_
select -assert-count 2 sdffe1/t:$_NOT_
select -assert-count 1 sdffce0/t:$_NOT_
-select -assert-count 2 sdffce1/t:$_NOT_
+select -assert-count 1 sdffce1/t:$_NOT_
select -assert-count 0 dff/t:$_MUX_
select -assert-count 3 dffe/t:$_MUX_
select -assert-count 3 sdff0/t:$_MUX_
@@ -537,13 +627,9 @@ select -assert-count 0 sdff1/t:$_MUX_
select -assert-count 8 sdffe0/t:$_MUX_
select -assert-count 4 sdffe1/t:$_MUX_
select -assert-count 8 sdffce0/t:$_MUX_
-select -assert-count 4 sdffce1/t:$_MUX_
-select -assert-count 0 t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ %% sdffce1/* %n %i
-select -assert-count 2 sdffce1/t:$_AND_
-select -assert-count 1 sdffce1/t:$_ORNOT_
-select -assert-count 1 sdffce1/t:$_ANDNOT_
+select -assert-count 8 sdffce1/t:$_MUX_
select -assert-count 27 t:$_SDFF_PP1_
-select -assert-none t:$_SDFF_PP1_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
+select -assert-none t:$_SDFF_PP1_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
design -load orig
dfflegalize -cell $_SDFF_PP1_ 1
@@ -554,7 +640,7 @@ select -assert-count 8 sdff0/t:$_NOT_
select -assert-count 7 sdff1/t:$_NOT_
select -assert-count 10 sdffe0/t:$_NOT_
select -assert-count 9 sdffe1/t:$_NOT_
-select -assert-count 10 sdffce0/t:$_NOT_
+select -assert-count 9 sdffce0/t:$_NOT_
select -assert-count 9 sdffce1/t:$_NOT_
select -assert-count 0 dff/t:$_MUX_
select -assert-count 3 dffe/t:$_MUX_
@@ -562,14 +648,10 @@ select -assert-count 0 sdff0/t:$_MUX_
select -assert-count 3 sdff1/t:$_MUX_
select -assert-count 4 sdffe0/t:$_MUX_
select -assert-count 8 sdffe1/t:$_MUX_
-select -assert-count 4 sdffce0/t:$_MUX_
+select -assert-count 8 sdffce0/t:$_MUX_
select -assert-count 8 sdffce1/t:$_MUX_
-select -assert-count 0 t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ %% sdffce0/* %n %i
-select -assert-count 2 sdffce0/t:$_AND_
-select -assert-count 1 sdffce0/t:$_ORNOT_
-select -assert-count 1 sdffce0/t:$_ANDNOT_
select -assert-count 27 t:$_SDFF_PP1_
-select -assert-none t:$_SDFF_PP1_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ORNOT_ t:$_ANDNOT_ top/* %% %n t:* %i
+select -assert-none t:$_SDFF_PP1_ t:$_MUX_ t:$_NOT_ top/* %% %n t:* %i
# Convert everything to SDFFEs.
diff --git a/tests/techmap/dfflegalize_dlatch.ys b/tests/techmap/dfflegalize_dlatch.ys
index b68ea741e..11683bc1a 100644
--- a/tests/techmap/dfflegalize_dlatch.ys
+++ b/tests/techmap/dfflegalize_dlatch.ys
@@ -11,6 +11,8 @@ design -save orig
equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_P_ x
equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP0_ x
equiv_opt -assert -multiclock dfflegalize -cell $_DLATCHSR_PPP_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFF_PP_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFFE_PPP_ x
# Convert everything to DFFs.
@@ -40,3 +42,23 @@ dfflegalize -cell $_DLATCHSR_PPP_ x
select -assert-count 1 t:$_NOT_
select -assert-count 2 t:$_DLATCHSR_PPP_
select -assert-none t:$_DLATCHSR_PPP_ t:$_NOT_ %% %n t:* %i
+
+
+# Convert everything to ALDFFs.
+
+design -load orig
+dfflegalize -cell $_ALDFF_PP_ x
+
+select -assert-count 1 t:$_NOT_
+select -assert-count 2 t:$_ALDFF_PP_
+select -assert-none t:$_ALDFF_PP_ t:$_NOT_ %% %n t:* %i
+
+
+# Convert everything to ALDFFEs.
+
+design -load orig
+dfflegalize -cell $_ALDFFE_PPP_ x
+
+select -assert-count 1 t:$_NOT_
+select -assert-count 2 t:$_ALDFFE_PPP_
+select -assert-none t:$_ALDFFE_PPP_ t:$_NOT_ %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_dlatch_const.ys b/tests/techmap/dfflegalize_dlatch_const.ys
index f30a534fd..159692249 100644
--- a/tests/techmap/dfflegalize_dlatch_const.ys
+++ b/tests/techmap/dfflegalize_dlatch_const.ys
@@ -24,14 +24,14 @@ equiv_opt -assert -multiclock dfflegalize -cell $_DFFSRE_PPPP_ 1
design -load orig
dfflegalize -cell $_DFF_PP0_ 01
-select -assert-count 12 t:$_NOT_
+select -assert-count 8 t:$_NOT_
select -assert-count 8 t:$_DFF_PP0_
select -assert-none t:$_DFF_PP0_ t:$_NOT_ %% %n t:* %i
design -load orig
dfflegalize -cell $_DFF_PP?_ 0
-select -assert-count 12 t:$_NOT_
+select -assert-count 8 t:$_NOT_
select -assert-count 4 t:$_DFF_PP0_
select -assert-count 4 t:$_DFF_PP1_
select -assert-none t:$_DFF_PP0_ t:$_DFF_PP1_ t:$_NOT_ %% %n t:* %i
@@ -41,13 +41,13 @@ select -assert-none t:$_DFF_PP0_ t:$_DFF_PP1_ t:$_NOT_ %% %n t:* %i
design -load orig
dfflegalize -cell $_DFFSRE_PPPP_ 0
-select -assert-count 12 t:$_NOT_
+select -assert-count 8 t:$_NOT_
select -assert-count 8 t:$_DFFSRE_PPPP_
select -assert-none t:$_DFFSRE_PPPP_ t:$_NOT_ %% %n t:* %i
design -load orig
dfflegalize -cell $_DFFSRE_PPPP_ 1
-select -assert-count 12 t:$_NOT_
+select -assert-count 8 t:$_NOT_
select -assert-count 8 t:$_DFFSRE_PPPP_
select -assert-none t:$_DFFSRE_PPPP_ t:$_NOT_ %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_dlatch_init.ys b/tests/techmap/dfflegalize_dlatch_init.ys
index ccc9e41d7..9324c6691 100644
--- a/tests/techmap/dfflegalize_dlatch_init.ys
+++ b/tests/techmap/dfflegalize_dlatch_init.ys
@@ -16,6 +16,10 @@ equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP1_ 0
equiv_opt -assert -multiclock dfflegalize -cell $_DLATCH_PP1_ 1
equiv_opt -assert -multiclock dfflegalize -cell $_DLATCHSR_PPP_ 0
equiv_opt -assert -multiclock dfflegalize -cell $_DLATCHSR_PPP_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFF_PP_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFF_PP_ 1
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFFE_PPP_ 0
+equiv_opt -assert -multiclock dfflegalize -cell $_ALDFFE_PPP_ 1
# Convert everything to DFFs.
@@ -80,3 +84,37 @@ dfflegalize -cell $_DLATCHSR_PPP_ 1
select -assert-count 5 t:$_NOT_
select -assert-count 2 t:$_DLATCHSR_PPP_
select -assert-none t:$_DLATCHSR_PPP_ t:$_NOT_ %% %n t:* %i
+
+
+# Convert everything to ALDFFs.
+
+design -load orig
+dfflegalize -cell $_ALDFF_PP_ 0
+
+select -assert-count 1 t:$_NOT_
+select -assert-count 2 t:$_ALDFF_PP_
+select -assert-none t:$_ALDFF_PP_ t:$_NOT_ %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_ALDFF_PP_ 1
+
+select -assert-count 5 t:$_NOT_
+select -assert-count 2 t:$_ALDFF_PP_
+select -assert-none t:$_ALDFF_PP_ t:$_NOT_ %% %n t:* %i
+
+
+# Convert everything to ALDFFEs.
+
+design -load orig
+dfflegalize -cell $_ALDFFE_PPP_ 0
+
+select -assert-count 1 t:$_NOT_
+select -assert-count 2 t:$_ALDFFE_PPP_
+select -assert-none t:$_ALDFFE_PPP_ t:$_NOT_ %% %n t:* %i
+
+design -load orig
+dfflegalize -cell $_ALDFFE_PPP_ 1
+
+select -assert-count 5 t:$_NOT_
+select -assert-count 2 t:$_ALDFFE_PPP_
+select -assert-none t:$_ALDFFE_PPP_ t:$_NOT_ %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_dlatchsr_init.ys b/tests/techmap/dfflegalize_dlatchsr_init.ys
index 2d33634d1..b38a9eb3b 100644
--- a/tests/techmap/dfflegalize_dlatchsr_init.ys
+++ b/tests/techmap/dfflegalize_dlatchsr_init.ys
@@ -66,8 +66,8 @@ select -assert-none t:$_DLATCH_PP0_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_O
design -load orig
dfflegalize -cell $_DLATCH_PP1_ 0
-select -assert-count 22 dlatchsr0/t:$_NOT_
-select -assert-count 26 dlatchsr1/t:$_NOT_
+select -assert-count 18 dlatchsr0/t:$_NOT_
+select -assert-count 22 dlatchsr1/t:$_NOT_
select -assert-count 4 dlatchsr0/t:$_MUX_
select -assert-count 4 dlatchsr1/t:$_MUX_
select -assert-count 12 dlatchsr0/t:$_DLATCH_PP1_
@@ -81,8 +81,8 @@ select -assert-none t:$_DLATCH_PP1_ t:$_MUX_ t:$_NOT_ t:$_AND_ t:$_ANDNOT_ t:$_O
design -load orig
dfflegalize -cell $_DLATCH_PP1_ 1
-select -assert-count 22 dlatchsr0/t:$_NOT_
-select -assert-count 26 dlatchsr1/t:$_NOT_
+select -assert-count 18 dlatchsr0/t:$_NOT_
+select -assert-count 22 dlatchsr1/t:$_NOT_
select -assert-count 4 dlatchsr0/t:$_MUX_
select -assert-count 4 dlatchsr1/t:$_MUX_
select -assert-count 12 dlatchsr0/t:$_DLATCH_PP1_
diff --git a/tests/techmap/dfflegalize_inv.ys b/tests/techmap/dfflegalize_inv.ys
index cb42e01a8..a74d74161 100644
--- a/tests/techmap/dfflegalize_inv.ys
+++ b/tests/techmap/dfflegalize_inv.ys
@@ -2,7 +2,7 @@
read_verilog -icells <<EOT
-module top(input C, E, R, S, D, output [64:0] Q);
+module top(input C, E, R, S, D, L, AD, output [71:0] Q);
$_DFF_P_ ff0 (.C(C), .D(D), .Q(Q[0]));
$_DFF_N_ ff1 (.C(C), .D(D), .Q(Q[1]));
@@ -88,16 +88,25 @@ $_SR_PP_ ff62 (.R(R), .S(S), .Q(Q[62]));
$_SR_PN_ ff63 (.R(R), .S(S), .Q(Q[63]));
$_SR_NP_ ff64 (.R(R), .S(S), .Q(Q[64]));
+$_ALDFF_PP_ ff65 (.C(C), .L(L), .AD(AD), .D(D), .Q(Q[65]));
+$_ALDFF_PN_ ff66 (.C(C), .L(L), .AD(AD), .D(D), .Q(Q[66]));
+$_ALDFF_NP_ ff67 (.C(C), .L(L), .AD(AD), .D(D), .Q(Q[67]));
+
+$_ALDFFE_PPP_ ff68 (.C(C), .L(L), .AD(AD), .D(D), .E(E), .Q(Q[68]));
+$_ALDFFE_PPN_ ff69 (.C(C), .L(L), .AD(AD), .D(D), .E(E), .Q(Q[69]));
+$_ALDFFE_PNP_ ff70 (.C(C), .L(L), .AD(AD), .D(D), .E(E), .Q(Q[70]));
+$_ALDFFE_NPP_ ff71 (.C(C), .L(L), .AD(AD), .D(D), .E(E), .Q(Q[71]));
+
endmodule
EOT
design -save orig
-equiv_opt -assert -multiclock dfflegalize -cell $_DFF_P_ x -cell $_DFFE_PP_ x -cell $_DFF_PP?_ x -cell $_DFFE_PP?P_ x -cell $_DFFSR_PPP_ x -cell $_DFFSRE_PPPP_ x -cell $_SDFF_PP?_ x -cell $_SDFFE_PP?P_ x -cell $_SDFFCE_PP?P_ x -cell $_DLATCH_P_ x -cell $_DLATCH_PP?_ x -cell $_DLATCHSR_PPP_ x -cell $_SR_PP_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_P_ x -cell $_DFFE_PP_ x -cell $_DFF_PP?_ x -cell $_DFFE_PP?P_ x -cell $_DFFSR_PPP_ x -cell $_DFFSRE_PPPP_ x -cell $_SDFF_PP?_ x -cell $_SDFFE_PP?P_ x -cell $_SDFFCE_PP?P_ x -cell $_DLATCH_P_ x -cell $_DLATCH_PP?_ x -cell $_DLATCHSR_PPP_ x -cell $_SR_PP_ x -cell $_ALDFF_PP_ x -cell $_ALDFFE_PPP_ x
design -load postopt
-select -assert-count 46 t:$_NOT_
+select -assert-count 51 t:$_NOT_
select -assert-count 2 t:$_DFF_P_
select -assert-count 3 t:$_DFFE_PP_
select -assert-count 3 t:$_DFF_PP0_
@@ -117,16 +126,18 @@ select -assert-count 3 t:$_DLATCH_PP0_
select -assert-count 3 t:$_DLATCH_PP1_
select -assert-count 4 t:$_DLATCHSR_PPP_
select -assert-count 3 t:$_SR_PP_
-select -assert-none t:$_DFF_P_ t:$_DFFE_PP_ t:$_DFF_PP?_ t:$_DFFE_PP?P_ t:$_DFFSR_PPP_ t:$_DFFSRE_PPPP_ t:$_SDFF_PP?_ t:$_SDFFE_PP?P_ t:$_SDFFCE_PP?P_ t:$_DLATCH_P_ t:$_DLATCH_PP?_ t:$_DLATCHSR_PPP_ t:$_SR_PP_ t:$_NOT_ %% %n t:* %i
+select -assert-count 3 t:$_ALDFF_PP_
+select -assert-count 4 t:$_ALDFFE_PPP_
+select -assert-none t:$_DFF_P_ t:$_DFFE_PP_ t:$_DFF_PP?_ t:$_DFFE_PP?P_ t:$_DFFSR_PPP_ t:$_DFFSRE_PPPP_ t:$_SDFF_PP?_ t:$_SDFFE_PP?P_ t:$_SDFFCE_PP?P_ t:$_DLATCH_P_ t:$_DLATCH_PP?_ t:$_DLATCHSR_PPP_ t:$_SR_PP_ t:$_ALDFF_PP_ t:$_ALDFFE_PPP_ t:$_NOT_ %% %n t:* %i
# Now try it again, targetting the opposite cells.
design -load orig
-equiv_opt -assert -multiclock dfflegalize -cell $_DFF_N_ x -cell $_DFFE_NN_ x -cell $_DFF_NN?_ x -cell $_DFFE_NN?N_ x -cell $_DFFSR_NNN_ x -cell $_DFFSRE_NNNN_ x -cell $_SDFF_NN?_ x -cell $_SDFFE_NN?N_ x -cell $_SDFFCE_NN?N_ x -cell $_DLATCH_N_ x -cell $_DLATCH_NN?_ x -cell $_DLATCHSR_NNN_ x -cell $_SR_NN_ x
+equiv_opt -assert -multiclock dfflegalize -cell $_DFF_N_ x -cell $_DFFE_NN_ x -cell $_DFF_NN?_ x -cell $_DFFE_NN?N_ x -cell $_DFFSR_NNN_ x -cell $_DFFSRE_NNNN_ x -cell $_SDFF_NN?_ x -cell $_SDFFE_NN?N_ x -cell $_SDFFCE_NN?N_ x -cell $_DLATCH_N_ x -cell $_DLATCH_NN?_ x -cell $_DLATCHSR_NNN_ x -cell $_SR_NN_ x -cell $_ALDFF_NN_ x -cell $_ALDFFE_NNN_ x
design -load postopt
-select -assert-count 122 t:$_NOT_
+select -assert-count 135 t:$_NOT_
select -assert-count 2 t:$_DFF_N_
select -assert-count 3 t:$_DFFE_NN_
select -assert-count 3 t:$_DFF_NN0_
@@ -146,7 +157,9 @@ select -assert-count 3 t:$_DLATCH_NN0_
select -assert-count 3 t:$_DLATCH_NN1_
select -assert-count 4 t:$_DLATCHSR_NNN_
select -assert-count 3 t:$_SR_NN_
-select -assert-none t:$_DFF_N_ t:$_DFFE_NN_ t:$_DFF_NN?_ t:$_DFFE_NN?N_ t:$_DFFSR_NNN_ t:$_DFFSRE_NNNN_ t:$_SDFF_NN?_ t:$_SDFFE_NN?N_ t:$_SDFFCE_NN?N_ t:$_DLATCH_N_ t:$_DLATCH_NN?_ t:$_DLATCHSR_NNN_ t:$_SR_NN_ t:$_NOT_ %% %n t:* %i
+select -assert-count 3 t:$_ALDFF_NN_
+select -assert-count 4 t:$_ALDFFE_NNN_
+select -assert-none t:$_DFF_N_ t:$_DFFE_NN_ t:$_DFF_NN?_ t:$_DFFE_NN?N_ t:$_DFFSR_NNN_ t:$_DFFSRE_NNNN_ t:$_SDFF_NN?_ t:$_SDFFE_NN?N_ t:$_SDFFCE_NN?N_ t:$_DLATCH_N_ t:$_DLATCH_NN?_ t:$_DLATCHSR_NNN_ t:$_SR_NN_ t:$_ALDFF_NN_ t:$_ALDFFE_NNN_ t:$_NOT_ %% %n t:* %i
# Second test: make sure set/reset/enable are inverted before clock.
diff --git a/tests/techmap/dfflegalize_minsrst.ys b/tests/techmap/dfflegalize_minsrst.ys
index 0fc40dc08..689066147 100644
--- a/tests/techmap/dfflegalize_minsrst.ys
+++ b/tests/techmap/dfflegalize_minsrst.ys
@@ -23,9 +23,9 @@ design -load postopt
select -assert-count 5 t:$_SDFF_PP0_
select -assert-count 1 t:$_SDFF_PP1_
-select -assert-count 3 t:$_SDFFE_PP0P_
+select -assert-count 1 t:$_SDFFE_PP0P_
select -assert-count 1 t:$_SDFFE_PP1P_
-select -assert-count 1 t:$_SDFFCE_PP0P_
+select -assert-count 3 t:$_SDFFCE_PP0P_
select -assert-count 1 t:$_SDFFCE_PP1P_
select -assert-count 8 t:$_MUX_
select -assert-count 0 n:ff0 %ci %ci t:$_MUX_ %i
diff --git a/tests/techmap/dfflegalize_sr.ys b/tests/techmap/dfflegalize_sr.ys
index 27e83be91..ee59a6e3c 100644
--- a/tests/techmap/dfflegalize_sr.ys
+++ b/tests/techmap/dfflegalize_sr.ys
@@ -39,7 +39,7 @@ select -assert-none t:$_DLATCH_PP0_ t:$_NOT_ %% %n t:* %i
design -load orig
dfflegalize -cell $_DLATCH_PP1_ x
-select -assert-count 8 t:$_NOT_
+select -assert-count 5 t:$_NOT_
select -assert-count 3 t:$_DLATCH_PP1_
select -assert-none t:$_DLATCH_PP1_ t:$_NOT_ %% %n t:* %i
diff --git a/tests/techmap/dfflegalize_sr_init.ys b/tests/techmap/dfflegalize_sr_init.ys
index 52b797b9e..9d724de29 100644
--- a/tests/techmap/dfflegalize_sr_init.ys
+++ b/tests/techmap/dfflegalize_sr_init.ys
@@ -12,7 +12,7 @@ $_SR_PN_ ff1 (.R(R), .S(S), .Q(Q[1]));
$_SR_NP_ ff2 (.R(R), .S(S), .Q(Q[2]));
endmodule
-module top(input C, E, R, D, output [5:0] Q);
+module top(input R, S, output [5:0] Q);
sr0 sr0_(.S(S), .R(R), .Q(Q[2:0]));
sr1 sr1_(.S(S), .R(R), .Q(Q[5:3]));
endmodule
@@ -103,8 +103,8 @@ select -assert-none t:$_DLATCH_PP0_ t:$_NOT_ t:$_ANDNOT_ t:$_OR_ t:$_AND_ top/*
design -load orig
dfflegalize -cell $_DLATCH_PP1_ 0
-select -assert-count 11 sr0/t:$_NOT_
-select -assert-count 8 sr1/t:$_NOT_
+select -assert-count 8 sr0/t:$_NOT_
+select -assert-count 5 sr1/t:$_NOT_
select -assert-count 3 sr0/t:$_DLATCH_PP1_
select -assert-count 3 sr1/t:$_DLATCH_PP1_
select -assert-count 1 sr0/t:$_ANDNOT_
@@ -118,8 +118,8 @@ select -assert-none t:$_DLATCH_PP1_ t:$_NOT_ t:$_ANDNOT_ t:$_OR_ t:$_AND_ top/*
design -load orig
dfflegalize -cell $_DLATCH_PP1_ 1
-select -assert-count 8 sr0/t:$_NOT_
-select -assert-count 11 sr1/t:$_NOT_
+select -assert-count 5 sr0/t:$_NOT_
+select -assert-count 8 sr1/t:$_NOT_
select -assert-count 3 sr0/t:$_DLATCH_PP1_
select -assert-count 3 sr1/t:$_DLATCH_PP1_
select -assert-count 0 sr0/t:$_ANDNOT_
diff --git a/tests/techmap/iopadmap.ys b/tests/techmap/iopadmap.ys
index df029b3a0..f8e6bc374 100644
--- a/tests/techmap/iopadmap.ys
+++ b/tests/techmap/iopadmap.ys
@@ -169,7 +169,7 @@ sub s2(.i(i[1]), .o(w[1]));
assign o = oe ? w : 2'bz;
endmodule
-module c(input i, oe, (* init=2'b00 *) inout io, output o1, o2);
+module c(input i, oe, (* init=1'b0 *) inout io, output o1, o2);
assign io = oe ? i : 1'bz;
assign {o1,o2} = {io,io};
endmodule
@@ -182,5 +182,5 @@ select -assert-count 1 a/c:s %co a/a:init=1'b1 %i
select -assert-count 1 a/a:init
select -assert-count 1 b/c:s* %co %a b/a:init=2'b1x %i
select -assert-count 1 b/a:init
-select -assert-count 1 c/t:iobuf %co c/a:init=2'b00 %i
+select -assert-count 1 c/t:iobuf %co c/a:init=1'b0 %i
select -assert-count 1 c/a:init
diff --git a/tests/techmap/mem_simple_4x1_runtest.sh b/tests/techmap/mem_simple_4x1_runtest.sh
index 9c41fa56a..b486de5c7 100644
--- a/tests/techmap/mem_simple_4x1_runtest.sh
+++ b/tests/techmap/mem_simple_4x1_runtest.sh
@@ -2,7 +2,7 @@
set -e
-../../yosys -b 'verilog -noattr' -o mem_simple_4x1_synth.v -p 'proc; opt; memory -nomap; techmap -map mem_simple_4x1_map.v;; techmap; opt; abc;; stat' mem_simple_4x1_uut.v
+../../yosys -b 'verilog -noattr' -o mem_simple_4x1_synth.v -p 'read_verilog mem_simple_4x1_uut.v; proc; opt; memory -nomap; techmap -map mem_simple_4x1_map.v;; techmap; opt; abc;; stat'
iverilog -o mem_simple_4x1_gold_tb mem_simple_4x1_tb.v mem_simple_4x1_uut.v
iverilog -o mem_simple_4x1_gate_tb mem_simple_4x1_tb.v mem_simple_4x1_synth.v mem_simple_4x1_cells.v
diff --git a/tests/techmap/recursive_runtest.sh b/tests/techmap/recursive_runtest.sh
index 0725ccf40..564d678fa 100644
--- a/tests/techmap/recursive_runtest.sh
+++ b/tests/techmap/recursive_runtest.sh
@@ -1,3 +1,3 @@
set -e
-../../yosys -p 'hierarchy -top top; techmap -map recursive_map.v -max_iter 1; select -assert-count 2 t:sub; select -assert-count 2 t:bar' recursive.v
+../../yosys -p 'read_verilog recursive.v; hierarchy -top top; techmap -map recursive_map.v -max_iter 1; select -assert-count 2 t:sub; select -assert-count 2 t:bar'
diff --git a/tests/techmap/zinit.ys b/tests/techmap/zinit.ys
index 1670573dd..bc07f40e6 100644
--- a/tests/techmap/zinit.ys
+++ b/tests/techmap/zinit.ys
@@ -20,7 +20,8 @@ EOT
equiv_opt -assert -multiclock zinit
design -load postopt
-select -assert-count 20 t:$_NOT_
+select -assert-count 16 t:$_NOT_
+select -assert-count 4 t:$xor
select -assert-count 1 w:unused a:init %i
select -assert-count 1 w:Q a:init=13'bxxxx1xxxxxxxx %i
select -assert-count 4 c:dff0 c:dff2 c:dff4 c:dff6 %% t:$_DFF_??1_ %i
@@ -52,7 +53,7 @@ design -load postopt
select -assert-count 0 t:$_NOT_
select -assert-count 1 w:unused a:init %i
-select -assert-count 1 w:Q a:init=13'bxxxx1xxxxxxxx %i
+select -assert-count 1 w:Q a:init=13'bx00x100000000 %i
select -assert-count 4 c:dff0 c:dff2 c:dff4 c:dff6 %% t:$_DFF_??0_ %i
select -assert-count 4 c:dff1 c:dff3 c:dff5 c:dff7 %% t:$_DFF_??1_ %i
@@ -142,7 +143,7 @@ EOT
zinit
select -assert-count 0 t:$_NOT_
-select -assert-count 0 w:Q a:init %i
+select -assert-count 1 w:Q a:init=24'b0 %i
select -assert-count 4 c:dff0 c:dff2 c:dff4 c:dff6 %% t:$_DFFE_??0P_ %i
select -assert-count 4 c:dff1 c:dff3 c:dff5 c:dff7 %% t:$_DFFE_??1P_ %i
select -assert-count 4 c:dff8 c:dff10 c:dff12 c:dff14 %% t:$_SDFF_??0_ %i
diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh
index 72a3d51eb..e4aef9917 100755
--- a/tests/tools/autotest.sh
+++ b/tests/tools/autotest.sh
@@ -197,7 +197,7 @@ do
test_passes -f "$frontend $include_opts" -p "hierarchy; synth -run coarse; techmap; opt; abc -dff" ${bn}_ref.${refext}
if [ -n "$firrtl2verilog" ]; then
if test -z "$xfirrtl" || ! grep "$fn" "$xfirrtl" ; then
- "$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep -nordff; proc; opt -nodffe -nosdff; fsm; opt; memory; opt -full -fine; pmuxtree" ${bn}_ref.${refext}
+ "$toolsdir"/../../yosys -b "firrtl" -o ${bn}_ref.fir -f "$frontend $include_opts" -p "prep; proc; opt -nodffe -nosdff; fsm; opt; memory; opt -full -fine; pmuxtree" ${bn}_ref.${refext}
$firrtl2verilog -i ${bn}_ref.fir -o ${bn}_ref.fir.v
test_passes -f "$frontend $include_opts" -p "hierarchy; proc; opt -nodffe -nosdff; fsm; opt; memory; opt -full -fine" ${bn}_ref.fir.v
fi
diff --git a/tests/tools/vcdcd.pl b/tests/tools/vcdcd.pl
index 58a92b44d..0f33371fb 100755
--- a/tests/tools/vcdcd.pl
+++ b/tests/tools/vcdcd.pl
@@ -11,7 +11,7 @@ $| = 1;
my $opt_width = 0;
my $opt_delay = 0;
-while (1)
+while ($#ARGV >= 0)
{
if ($ARGV[0] eq '-w') {
$opt_width = +$ARGV[1];
@@ -74,10 +74,10 @@ for my $net (sort keys %gold_signals_hash) {
# next unless $net eq "tst_bench_top.i2c_top.byte_controller.bit_controller.cnt";
my %orig_net_names;
print "common signal: $net";
- for my $fullname (keys $gold_signals_hash{$net}) {
+ for my $fullname (keys %{$gold_signals_hash{$net}}) {
$orig_net_names{$fullname} = 1;
}
- for my $fullname (keys $gate_signals_hash{$net}) {
+ for my $fullname (keys %{$gate_signals_hash{$net}}) {
$orig_net_names{$fullname} = 1;
}
for my $net (sort keys %orig_net_names) {
diff --git a/tests/various/abc9.ys b/tests/various/abc9.ys
index a9880c722..e0add714b 100644
--- a/tests/various/abc9.ys
+++ b/tests/various/abc9.ys
@@ -90,7 +90,7 @@ $_DFF_N_ ff4(.C(clk), .D(1'b1), .Q(z));
endmodule
EOT
simplemap
-equiv_opt abc9 -lut 4 -dff
+equiv_opt -assert abc9 -lut 4 -dff
design -load postopt
cd abc9_test038
select -assert-count 3 t:$_DFF_N_
@@ -99,3 +99,58 @@ clean
select -assert-count 2 a:init
select -assert-count 1 w:w a:init %i
select -assert-count 1 c:ff4 %co c:ff4 %d %a a:init %i
+
+
+# Check that non-dangling ABC9 black-boxes are preserved
+design -reset
+read_verilog -specify <<EOT
+(* abc9_box, blackbox *)
+module mux_with_param(input I0, I1, S, output O);
+parameter P = 0;
+specify
+ (I0 => O) = P;
+ (I1 => O) = P;
+ (S => O) = P;
+endspecify
+endmodule
+
+module abc9_test039(output O);
+ mux_with_param #(.P(1)) m (
+ .I0(1'b1),
+ .I1(1'b1),
+ .O(O),
+ .S(1'b0)
+ );
+endmodule
+EOT
+abc9 -lut 4
+cd abc9_test039
+select -assert-count 1 t:mux_with_param
+
+
+# Check that dangling ABC9 black-boxes are swept away
+design -reset
+read_verilog -specify <<EOT
+(* abc9_box, blackbox *)
+module mux_with_param(input I0, I1, S, output O);
+parameter P = 0;
+specify
+ (I0 => O) = P;
+ (I1 => O) = P;
+ (S => O) = P;
+endspecify
+endmodule
+
+module abc9_test040(output O);
+ wire w;
+ mux_with_param #(.P(1)) m (
+ .I0(1'b1),
+ .I1(1'b1),
+ .O(w),
+ .S(1'b0)
+ );
+endmodule
+EOT
+abc9 -lut 4
+cd abc9_test040
+select -assert-count 0 t:mux_with_param
diff --git a/tests/various/async.sh b/tests/various/async.sh
index 7c41d6d94..e83935d02 100644
--- a/tests/various/async.sh
+++ b/tests/various/async.sh
@@ -1,9 +1,9 @@
#!/bin/bash
set -ex
-../../yosys -q -o async_syn.v -p 'synth; rename uut syn' async.v
-../../yosys -q -o async_prp.v -p 'prep; rename uut prp' async.v
-../../yosys -q -o async_a2s.v -p 'prep; async2sync; rename uut a2s' async.v
-../../yosys -q -o async_ffl.v -p 'prep; clk2fflogic; rename uut ffl' async.v
+../../yosys -q -o async_syn.v -r uut -p 'synth; rename uut syn' async.v
+../../yosys -q -o async_prp.v -r uut -p 'prep; rename uut prp' async.v
+../../yosys -q -o async_a2s.v -r uut -p 'prep; async2sync; rename uut a2s' async.v
+../../yosys -q -o async_ffl.v -r uut -p 'prep; clk2fflogic; rename uut ffl' async.v
iverilog -o async_sim -DTESTBENCH async.v async_???.v
vvp -N async_sim > async.out
tail async.out
diff --git a/tests/various/blackbox_wb.ys b/tests/various/blackbox_wb.ys
new file mode 100644
index 000000000..f9c9bec06
--- /dev/null
+++ b/tests/various/blackbox_wb.ys
@@ -0,0 +1,14 @@
+read_verilog <<EOT
+(* whitebox *)
+module box(input a, output q);
+assign q = ~a;
+endmodule
+
+module top(input a, output q);
+box box_i(.a(a), .q(q));
+endmodule
+EOT
+select -assert-count 1 =box/t:$not
+blackbox =box
+select -assert-count 0 =A:whitebox
+select -assert-count 0 =box/t:$not
diff --git a/tests/various/logger_fail.sh b/tests/various/logger_fail.sh
new file mode 100755
index 000000000..19b650007
--- /dev/null
+++ b/tests/various/logger_fail.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+fail() {
+ echo "$1" >&2
+ exit 1
+}
+
+runTest() {
+ desc="$1"
+ want="$2"
+ shift 2
+ echo "running '$desc' with args $@"
+ output=`../../yosys -q "$@" 2>&1`
+ if [ $? -ne 1 ]; then
+ fail "exit code for '$desc' was not 1"
+ fi
+ if [ "$output" != "$want" ]; then
+ fail "output for '$desc' did not match"
+ fi
+}
+
+unmet() {
+ kind=$1
+ runTest "unmet $kind" \
+ "ERROR: Expected $kind pattern 'foobar' not found !" \
+ -p "logger -expect $kind \"foobar\" 1"
+}
+
+unmet log
+unmet warning
+unmet error
+
+runTest "too many logs" \
+ "ERROR: Expected log pattern 'statistics' found 2 time(s), instead of 1 time(s) !" \
+ -p "logger -expect log \"statistics\" 1" -p stat -p stat
+
+runTest "too many warnings" \
+ "Warning: Found log message matching -W regex:
+Printing statistics.
+ERROR: Expected warning pattern 'statistics' found 2 time(s), instead of 1 time(s) !" \
+ -p "logger -warn \"Printing statistics\"" \
+ -p "logger -expect warning \"statistics\" 1" -p stat -p stat
diff --git a/tests/various/muxpack.v b/tests/various/muxpack.v
index 33ece1f16..752f9ba48 100644
--- a/tests/various/muxpack.v
+++ b/tests/various/muxpack.v
@@ -154,7 +154,7 @@ always @*
o <= i[4*W+:W];
endmodule
-module cliffordwolf_nonexclusive_select (
+module clairexen_nonexclusive_select (
input wire x, y, z,
input wire a, b, c, d,
output reg o
@@ -167,7 +167,7 @@ module cliffordwolf_nonexclusive_select (
end
endmodule
-module cliffordwolf_freduce (
+module clairexen_freduce (
input wire [1:0] s,
input wire a, b, c, d,
output reg [3:0] o
diff --git a/tests/various/muxpack.ys b/tests/various/muxpack.ys
index 3e90419af..d73fc44b4 100644
--- a/tests/various/muxpack.ys
+++ b/tests/various/muxpack.ys
@@ -167,7 +167,7 @@ miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -show-ports miter
design -load read
-hierarchy -top cliffordwolf_nonexclusive_select
+hierarchy -top clairexen_nonexclusive_select
prep
design -save gold
muxpack
@@ -182,7 +182,7 @@ miter -equiv -flatten -make_assert -make_outputs gold gate miter
sat -verify -prove-asserts -show-ports miter
#design -load read
-#hierarchy -top cliffordwolf_freduce
+#hierarchy -top clairexen_freduce
#prep
#design -save gold
#proc; opt; freduce; opt
diff --git a/tests/various/param_struct.ys b/tests/various/param_struct.ys
new file mode 100644
index 000000000..6d7a7c6ad
--- /dev/null
+++ b/tests/various/param_struct.ys
@@ -0,0 +1,51 @@
+read_verilog -sv << EOF
+package p;
+typedef struct packed {
+ logic a;
+ logic b;
+} struct_t;
+
+typedef struct packed {
+ struct_t g;
+ logic [2:0] h;
+} nested_struct_t;
+
+typedef union packed {
+ logic [4:0] x;
+} nested_union_t;
+
+parameter struct_t c = {1'b1, 1'b0};
+parameter nested_struct_t x = {{1'b1, 1'b0}, 1'b1, 1'b1, 1'b1};
+endpackage
+
+module dut ();
+parameter p::struct_t d = p::c;
+parameter p::nested_struct_t i = p::x;
+
+parameter p::nested_union_t u = {5'b11001};
+
+localparam e = d.a;
+localparam f = d.b;
+
+localparam j = i.g.a;
+localparam k = i.g.b;
+localparam l = i.h;
+localparam m = i.g;
+
+localparam o = u.x;
+
+always_comb begin
+ assert(d == 2'b10);
+ assert(e == 1'b1);
+ assert(f == 1'b0);
+ assert(j == 1'b1);
+ assert(k == 1'b0);
+ assert(l == 3'b111);
+// TODO: support access to whole sub-structs and unions
+// assert(m == 2'b10);
+ assert(u == 5'b11001);
+end
+endmodule
+EOF
+hierarchy; proc; opt
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
diff --git a/tests/various/sta.ys b/tests/various/sta.ys
new file mode 100644
index 000000000..156c31c47
--- /dev/null
+++ b/tests/various/sta.ys
@@ -0,0 +1,81 @@
+read_verilog -specify <<EOT
+module buffer(input i, output o);
+specify
+(i => o) = 10;
+endspecify
+endmodule
+
+module top(input i);
+wire w;
+buffer b(.i(i), .o(w));
+endmodule
+EOT
+
+logger -expect warning "Critical-path does not terminate in a recognised endpoint\." 1
+sta
+
+
+design -reset
+read_verilog -specify <<EOT
+module top(input i, output o, p);
+assign o = i;
+endmodule
+EOT
+
+logger -expect log "No timing paths found\." 1
+sta
+
+
+design -reset
+read_verilog -specify <<EOT
+module buffer(input i, output o);
+specify
+(i => o) = 10;
+endspecify
+endmodule
+
+module top(input i, output o, p);
+buffer b(.i(i), .o(o));
+endmodule
+EOT
+
+sta
+
+
+design -reset
+read_verilog -specify <<EOT
+module buffer(input i, output o);
+specify
+(i => o) = 10;
+endspecify
+endmodule
+
+module top(input i, output o, p);
+buffer b(.i(i), .o(o));
+const0 c(.o(p));
+endmodule
+EOT
+
+logger -expect warning "Cell type 'const0' not recognised! Ignoring\." 1
+sta
+
+
+design -reset
+read_verilog -specify <<EOT
+module buffer(input i, output o);
+specify
+(i => o) = 10;
+endspecify
+endmodule
+module const0(output o);
+endmodule
+
+module top(input i, output o, p);
+buffer b(.i(i), .o(o));
+const0 c(.o(p));
+endmodule
+EOT
+
+sta
+
+logger -expect-no-warnings
diff --git a/tests/verilog/.gitignore b/tests/verilog/.gitignore
index 34da23437..96ebe20ba 100644
--- a/tests/verilog/.gitignore
+++ b/tests/verilog/.gitignore
@@ -3,3 +3,4 @@
/run-test.mk
/const_arst.v
/const_sr.v
+/doubleslash.v
diff --git a/tests/verilog/absurd_width.ys b/tests/verilog/absurd_width.ys
new file mode 100644
index 000000000..c0d2af4c2
--- /dev/null
+++ b/tests/verilog/absurd_width.ys
@@ -0,0 +1,17 @@
+logger -expect error "Expression width 1073741824 exceeds implementation limit of 16777216!" 1
+read_verilog <<EOF
+module top(
+ input inp,
+ output out
+);
+ assign out =
+ {1024 {
+ {1024 {
+ {1024 {
+ inp
+ }}
+ }}
+ }}
+ ;
+endmodule
+EOF
diff --git a/tests/verilog/absurd_width_const.ys b/tests/verilog/absurd_width_const.ys
new file mode 100644
index 000000000..b7191fd0d
--- /dev/null
+++ b/tests/verilog/absurd_width_const.ys
@@ -0,0 +1,16 @@
+logger -expect error "Expression width 1073741824 exceeds implementation limit of 16777216!" 1
+read_verilog <<EOF
+module top(
+ output out
+);
+ assign out =
+ {1024 {
+ {1024 {
+ {1024 {
+ 1'b1
+ }}
+ }}
+ }}
+ ;
+endmodule
+EOF
diff --git a/tests/verilog/always_comb_latch_1.ys b/tests/verilog/always_comb_latch_1.ys
new file mode 100644
index 000000000..c98c79fa2
--- /dev/null
+++ b/tests/verilog/always_comb_latch_1.ys
@@ -0,0 +1,13 @@
+read_verilog -sv <<EOF
+module top;
+logic x;
+always_comb begin
+ logic y;
+ if (x)
+ y = 1;
+ x = y;
+end
+endmodule
+EOF
+logger -expect error "^Latch inferred for signal `\\top\.\$unnamed_block\$1\.y' from always_comb process" 1
+proc
diff --git a/tests/verilog/always_comb_latch_2.ys b/tests/verilog/always_comb_latch_2.ys
new file mode 100644
index 000000000..567205a53
--- /dev/null
+++ b/tests/verilog/always_comb_latch_2.ys
@@ -0,0 +1,15 @@
+read_verilog -sv <<EOF
+module top;
+logic x;
+always_comb begin
+ logic y;
+ if (x)
+ x = 1;
+ else
+ y = 1;
+ x = y;
+end
+endmodule
+EOF
+logger -expect error "^Latch inferred for signal `\\top\.\$unnamed_block\$1\.y' from always_comb process" 1
+proc
diff --git a/tests/verilog/always_comb_latch_3.ys b/tests/verilog/always_comb_latch_3.ys
new file mode 100644
index 000000000..b9b028ac7
--- /dev/null
+++ b/tests/verilog/always_comb_latch_3.ys
@@ -0,0 +1,20 @@
+read_verilog -sv <<EOF
+module top;
+logic x;
+logic z;
+assign z = 1'b1;
+always_comb begin
+ logic y;
+ case (x)
+ 1'b0:
+ y = 1;
+ endcase
+ if (z)
+ x = y;
+ else
+ x = 1'b0;
+end
+endmodule
+EOF
+logger -expect error "^Latch inferred for signal `\\top\.\$unnamed_block\$1\.y' from always_comb process" 1
+proc
diff --git a/tests/verilog/always_comb_latch_4.ys b/tests/verilog/always_comb_latch_4.ys
new file mode 100644
index 000000000..46b78801b
--- /dev/null
+++ b/tests/verilog/always_comb_latch_4.ys
@@ -0,0 +1,17 @@
+read_verilog -sv <<EOF
+module top;
+parameter AVOID_LATCH = 0;
+logic x, z;
+assign z = 1'b1;
+always_comb begin
+ logic y;
+ if (z)
+ y = 0;
+ for (int i = 1; i == AVOID_LATCH; i++)
+ y = 1;
+ x = z ? y : 1'b0;
+end
+endmodule
+EOF
+logger -expect error "^Latch inferred for signal `\\top\.\$unnamed_block\$3\.y' from always_comb process" 1
+proc
diff --git a/tests/verilog/always_comb_nolatch_1.ys b/tests/verilog/always_comb_nolatch_1.ys
new file mode 100644
index 000000000..4d1952b52
--- /dev/null
+++ b/tests/verilog/always_comb_nolatch_1.ys
@@ -0,0 +1,16 @@
+read_verilog -sv <<EOF
+module top;
+logic [4:0] x;
+logic z;
+assign z = 1'b1;
+always_comb begin
+ x = '0;
+ if (z) begin
+ for (int i = 0; i < 5; i++) begin
+ x[i] = 1'b1;
+ end
+ end
+end
+endmodule
+EOF
+proc
diff --git a/tests/verilog/always_comb_nolatch_2.ys b/tests/verilog/always_comb_nolatch_2.ys
new file mode 100644
index 000000000..2ec6ca0f4
--- /dev/null
+++ b/tests/verilog/always_comb_nolatch_2.ys
@@ -0,0 +1,17 @@
+read_verilog -sv <<EOF
+module top;
+logic [4:0] x;
+logic z;
+assign z = 1'b1;
+always_comb begin
+ x = '0;
+ if (z) begin
+ int i;
+ for (i = 0; i < 5; i++) begin
+ x[i] = 1'b1;
+ end
+ end
+end
+endmodule
+EOF
+proc
diff --git a/tests/verilog/always_comb_nolatch_3.ys b/tests/verilog/always_comb_nolatch_3.ys
new file mode 100644
index 000000000..33f9833a2
--- /dev/null
+++ b/tests/verilog/always_comb_nolatch_3.ys
@@ -0,0 +1,21 @@
+read_verilog -sv <<EOF
+module top;
+logic x;
+logic z;
+assign z = 1'b1;
+always_comb begin
+ logic y;
+ case (x)
+ 1'b0:
+ y = 1;
+ default:
+ y = 0;
+ endcase
+ if (z)
+ x = y;
+ else
+ x = 1'b0;
+end
+endmodule
+EOF
+proc
diff --git a/tests/verilog/always_comb_nolatch_4.ys b/tests/verilog/always_comb_nolatch_4.ys
new file mode 100644
index 000000000..bc29b2771
--- /dev/null
+++ b/tests/verilog/always_comb_nolatch_4.ys
@@ -0,0 +1,16 @@
+read_verilog -sv <<EOF
+module top;
+parameter AVOID_LATCH = 1;
+logic x, z;
+assign z = 1'b1;
+always_comb begin
+ logic y;
+ if (z)
+ y = 0;
+ for (int i = 1; i == AVOID_LATCH; i++)
+ y = 1;
+ x = z ? y : 1'b0;
+end
+endmodule
+EOF
+proc
diff --git a/tests/verilog/block_end_label_only.ys b/tests/verilog/block_end_label_only.ys
new file mode 100644
index 000000000..5db1c7879
--- /dev/null
+++ b/tests/verilog/block_end_label_only.ys
@@ -0,0 +1,9 @@
+logger -expect error "Begin label missing where end label \(incorrect_name\) was given\." 1
+read_verilog -sv <<EOF
+module top;
+initial
+ begin
+ $display("HI");
+ end : incorrect_name
+endmodule
+EOF
diff --git a/tests/verilog/block_end_label_wrong.ys b/tests/verilog/block_end_label_wrong.ys
new file mode 100644
index 000000000..47dbbe32f
--- /dev/null
+++ b/tests/verilog/block_end_label_wrong.ys
@@ -0,0 +1,9 @@
+logger -expect error "Begin label \(correct_name\) and end label \(incorrect_name\) don't match\." 1
+read_verilog -sv <<EOF
+module top;
+initial
+ begin : correct_name
+ $display("HI");
+ end : incorrect_name
+endmodule
+EOF
diff --git a/tests/verilog/doubleslash.ys b/tests/verilog/doubleslash.ys
new file mode 100644
index 000000000..c41673ee5
--- /dev/null
+++ b/tests/verilog/doubleslash.ys
@@ -0,0 +1,21 @@
+read_verilog -sv <<EOT
+module doubleslash
+ (input logic a,
+ input logic b,
+ output logic z);
+
+ logic \a//b ;
+
+ assign \a//b = a & b;
+ assign z = ~\a//b ;
+
+endmodule : doubleslash
+EOT
+
+hierarchy
+proc
+opt -full
+
+write_verilog doubleslash.v
+design -reset
+read_verilog doubleslash.v
diff --git a/tests/verilog/for_decl_no_init.ys b/tests/verilog/for_decl_no_init.ys
new file mode 100644
index 000000000..68c1584e0
--- /dev/null
+++ b/tests/verilog/for_decl_no_init.ys
@@ -0,0 +1,9 @@
+logger -expect error "For loop variable declaration is missing initialization!" 1
+read_verilog -sv <<EOT
+module top;
+ integer z;
+ initial
+ for (integer i; i < 10; i = i + 1)
+ z = i;
+endmodule
+EOT
diff --git a/tests/verilog/for_decl_no_sv.ys b/tests/verilog/for_decl_no_sv.ys
new file mode 100644
index 000000000..34edddff7
--- /dev/null
+++ b/tests/verilog/for_decl_no_sv.ys
@@ -0,0 +1,9 @@
+logger -expect error "For loop inline variable declaration is only supported in SystemVerilog mode!" 1
+read_verilog <<EOT
+module top;
+ integer z;
+ initial
+ for (integer i = 1; i < 10; i = i + 1)
+ z = i;
+endmodule
+EOT
diff --git a/tests/verilog/for_decl_shadow.sv b/tests/verilog/for_decl_shadow.sv
new file mode 100644
index 000000000..f6948f97e
--- /dev/null
+++ b/tests/verilog/for_decl_shadow.sv
@@ -0,0 +1,32 @@
+module gate(x);
+ output reg [15:0] x;
+ if (1) begin : gen
+ integer x;
+ initial begin
+ for (integer x = 5; x < 10; x++)
+ if (x == 5)
+ gen.x = 0;
+ else
+ gen.x += 2 ** x;
+ x = x * 2;
+ end
+ end
+ initial x = gen.x;
+endmodule
+
+module gold(x);
+ output reg [15:0] x;
+ if (1) begin : gen
+ integer x;
+ integer z;
+ initial begin
+ for (z = 5; z < 10; z++)
+ if (z == 5)
+ x = 0;
+ else
+ x += 2 ** z;
+ x = x * 2;
+ end
+ end
+ initial x = gen.x;
+endmodule
diff --git a/tests/verilog/for_decl_shadow.ys b/tests/verilog/for_decl_shadow.ys
new file mode 100644
index 000000000..d2dca715e
--- /dev/null
+++ b/tests/verilog/for_decl_shadow.ys
@@ -0,0 +1,6 @@
+read_verilog -sv for_decl_shadow.sv
+hierarchy
+proc
+equiv_make gold gate equiv
+equiv_simple
+equiv_status -assert
diff --git a/tests/verilog/func_typename_ret.sv b/tests/verilog/func_typename_ret.sv
new file mode 100644
index 000000000..423975f97
--- /dev/null
+++ b/tests/verilog/func_typename_ret.sv
@@ -0,0 +1,35 @@
+typedef logic [1:0] T;
+
+package P;
+ typedef logic [3:0] S;
+endpackage
+
+module gate(
+ output wire [31:0] out1, out2
+);
+ function automatic T func1;
+ input reg signed inp;
+ func1 = inp;
+ endfunction
+ assign out1 = func1(1);
+ function automatic P::S func2;
+ input reg signed inp;
+ func2 = inp;
+ endfunction
+ assign out2 = func2(1);
+endmodule
+
+module gold(
+ output wire [31:0] out1, out2
+);
+ function automatic [1:0] func1;
+ input reg signed inp;
+ func1 = inp;
+ endfunction
+ assign out1 = func1(1);
+ function automatic [3:0] func2;
+ input reg signed inp;
+ func2 = inp;
+ endfunction
+ assign out2 = func2(1);
+endmodule
diff --git a/tests/verilog/func_typename_ret.ys b/tests/verilog/func_typename_ret.ys
new file mode 100644
index 000000000..7f6049961
--- /dev/null
+++ b/tests/verilog/func_typename_ret.ys
@@ -0,0 +1,5 @@
+read_verilog -sv func_typename_ret.sv
+proc
+equiv_make gold gate equiv
+equiv_simple
+equiv_status -assert
diff --git a/tests/verilog/gen_block_end_label_only.ys b/tests/verilog/gen_block_end_label_only.ys
new file mode 100644
index 000000000..60dc0476a
--- /dev/null
+++ b/tests/verilog/gen_block_end_label_only.ys
@@ -0,0 +1,9 @@
+logger -expect error "Begin label missing where end label \(incorrect_name\) was given\." 1
+read_verilog -sv <<EOF
+module top;
+if (1)
+ begin
+ initial $display("HI");
+ end : incorrect_name
+endmodule
+EOF
diff --git a/tests/verilog/gen_block_end_label_wrong.ys b/tests/verilog/gen_block_end_label_wrong.ys
new file mode 100644
index 000000000..43cfc8773
--- /dev/null
+++ b/tests/verilog/gen_block_end_label_wrong.ys
@@ -0,0 +1,9 @@
+logger -expect error "Begin label \(correct_name\) and end label \(incorrect_name\) don't match\." 1
+read_verilog -sv <<EOF
+module top;
+if (1)
+ begin : correct_name
+ initial $display("HI");
+ end : incorrect_name
+endmodule
+EOF
diff --git a/tests/verilog/genfor_decl_no_init.ys b/tests/verilog/genfor_decl_no_init.ys
new file mode 100644
index 000000000..348899195
--- /dev/null
+++ b/tests/verilog/genfor_decl_no_init.ys
@@ -0,0 +1,7 @@
+logger -expect error "Generate for loop variable declaration is missing initialization!" 1
+read_verilog -sv <<EOT
+module top;
+ for (genvar i; i < 10; i = i + 1)
+ wire x;
+endmodule
+EOT
diff --git a/tests/verilog/genfor_decl_no_sv.ys b/tests/verilog/genfor_decl_no_sv.ys
new file mode 100644
index 000000000..124a27c28
--- /dev/null
+++ b/tests/verilog/genfor_decl_no_sv.ys
@@ -0,0 +1,7 @@
+logger -expect error "Generate for loop inline variable declaration is only supported in SystemVerilog mode!" 1
+read_verilog <<EOT
+module top;
+ for (genvar i = 1; i < 10; i = i + 1)
+ wire x;
+endmodule
+EOT
diff --git a/tests/verilog/genvar_loop_decl_1.sv b/tests/verilog/genvar_loop_decl_1.sv
new file mode 100644
index 000000000..b503f75da
--- /dev/null
+++ b/tests/verilog/genvar_loop_decl_1.sv
@@ -0,0 +1,18 @@
+`default_nettype none
+
+module gate(a);
+ for (genvar i = 0; i < 2; i++)
+ wire [i:0] x = '1;
+
+ output wire [32:0] a;
+ assign a = {1'b0, genblk1[0].x, 1'b0, genblk1[1].x, 1'b0};
+endmodule
+
+module gold(a);
+ genvar i;
+ for (i = 0; i < 2; i++)
+ wire [i:0] x = '1;
+
+ output wire [32:0] a;
+ assign a = {1'b0, genblk1[0].x, 1'b0, genblk1[1].x, 1'b0};
+endmodule
diff --git a/tests/verilog/genvar_loop_decl_1.ys b/tests/verilog/genvar_loop_decl_1.ys
new file mode 100644
index 000000000..ded486248
--- /dev/null
+++ b/tests/verilog/genvar_loop_decl_1.ys
@@ -0,0 +1,14 @@
+read_verilog -sv genvar_loop_decl_1.sv
+
+select -assert-count 1 gate/genblk1[0].x
+select -assert-count 1 gate/genblk1[1].x
+select -assert-count 0 gate/genblk1[2].x
+
+select -assert-count 1 gold/genblk1[0].x
+select -assert-count 1 gold/genblk1[1].x
+select -assert-count 0 gold/genblk1[2].x
+
+proc
+equiv_make gold gate equiv
+equiv_simple
+equiv_status -assert
diff --git a/tests/verilog/genvar_loop_decl_2.sv b/tests/verilog/genvar_loop_decl_2.sv
new file mode 100644
index 000000000..c5a85ef11
--- /dev/null
+++ b/tests/verilog/genvar_loop_decl_2.sv
@@ -0,0 +1,30 @@
+`default_nettype none
+
+module gate(out);
+ wire [3:0] x;
+ for (genvar x = 0; x < 2; x++) begin : blk
+ localparam w = x;
+ if (x == 0) begin : sub
+ wire [w:0] x;
+ end
+ end
+ assign x = 2;
+ assign blk[0].sub.x = '1;
+ output wire [9:0] out;
+ assign out = {1'bx, x, blk[0].sub.x};
+endmodule
+
+module gold(out);
+ wire [3:0] x;
+ genvar z;
+ for (z = 0; z < 2; z++) begin : blk
+ localparam w = z;
+ if (z == 0) begin : sub
+ wire [w:0] x;
+ end
+ end
+ assign x = 2;
+ assign blk[0].sub.x = '1;
+ output wire [9:0] out;
+ assign out = {1'bx, x, blk[0].sub.x};
+endmodule
diff --git a/tests/verilog/genvar_loop_decl_2.ys b/tests/verilog/genvar_loop_decl_2.ys
new file mode 100644
index 000000000..52fdeb49c
--- /dev/null
+++ b/tests/verilog/genvar_loop_decl_2.ys
@@ -0,0 +1,5 @@
+read_verilog -sv genvar_loop_decl_2.sv
+proc
+equiv_make gold gate equiv
+equiv_simple
+equiv_status -assert
diff --git a/tests/verilog/genvar_loop_decl_3.sv b/tests/verilog/genvar_loop_decl_3.sv
new file mode 100644
index 000000000..4d6d2366d
--- /dev/null
+++ b/tests/verilog/genvar_loop_decl_3.sv
@@ -0,0 +1,28 @@
+`default_nettype none
+
+module gate(x, y);
+ output reg [15:0] x, y;
+ if (1) begin : gen
+ integer x, y;
+ for (genvar x = 0; x < 2; x++)
+ if (x == 0)
+ initial gen.x = 10;
+ assign y = x + 1;
+ end
+ initial x = gen.x;
+ assign y = gen.y;
+endmodule
+
+module gold(x, y);
+ output reg [15:0] x, y;
+ if (1) begin : gen
+ integer x, y;
+ genvar z;
+ for (z = 0; z < 2; z++)
+ if (z == 0)
+ initial x = 10;
+ assign y = x + 1;
+ end
+ initial x = gen.x;
+ assign y = gen.y;
+endmodule
diff --git a/tests/verilog/genvar_loop_decl_3.ys b/tests/verilog/genvar_loop_decl_3.ys
new file mode 100644
index 000000000..19f754124
--- /dev/null
+++ b/tests/verilog/genvar_loop_decl_3.ys
@@ -0,0 +1,5 @@
+read_verilog -sv genvar_loop_decl_3.sv
+proc
+equiv_make gold gate equiv
+equiv_simple
+equiv_status -assert
diff --git a/tests/verilog/global_parameter.ys b/tests/verilog/global_parameter.ys
new file mode 100644
index 000000000..a7a3cddc7
--- /dev/null
+++ b/tests/verilog/global_parameter.ys
@@ -0,0 +1,16 @@
+read_verilog -sv <<EOF
+parameter P = 1;
+module example(
+ output integer out
+);
+ assign out = P;
+endmodule
+module top(
+ output integer out
+);
+ example #(2) e1(out);
+endmodule
+EOF
+
+logger -expect error "Can't find object for defparam" 1
+hierarchy
diff --git a/tests/verilog/ifdef_nest.ys b/tests/verilog/ifdef_nest.ys
new file mode 100644
index 000000000..2202109aa
--- /dev/null
+++ b/tests/verilog/ifdef_nest.ys
@@ -0,0 +1,7 @@
+read_verilog <<EOF
+`ifndef a
+`ifdef b
+`endif
+`else
+`endif
+EOF
diff --git a/tests/verilog/ifdef_unterminated.ys b/tests/verilog/ifdef_unterminated.ys
new file mode 100644
index 000000000..ce511fa8f
--- /dev/null
+++ b/tests/verilog/ifdef_unterminated.ys
@@ -0,0 +1,4 @@
+logger -expect error "Unterminated preprocessor conditional!" 1
+read_verilog <<EOF
+`ifndef a
+EOF
diff --git a/tests/verilog/localparam_no_default_1.ys b/tests/verilog/localparam_no_default_1.ys
new file mode 100644
index 000000000..426a48a1c
--- /dev/null
+++ b/tests/verilog/localparam_no_default_1.ys
@@ -0,0 +1,17 @@
+logger -expect-no-warnings
+read_verilog -sv <<EOF
+module Module #(
+ localparam X = 1
+);
+endmodule
+EOF
+
+design -reset
+
+logger -expect error "localparam initialization is missing!" 1
+read_verilog <<EOF
+module Module #(
+ localparam X
+);
+endmodule
+EOF
diff --git a/tests/verilog/localparam_no_default_2.ys b/tests/verilog/localparam_no_default_2.ys
new file mode 100644
index 000000000..b7b2622ad
--- /dev/null
+++ b/tests/verilog/localparam_no_default_2.ys
@@ -0,0 +1,15 @@
+logger -expect-no-warnings
+read_verilog -sv <<EOF
+module Module;
+ localparam X = 1;
+endmodule
+EOF
+
+design -reset
+
+logger -expect error "localparam initialization is missing!" 1
+read_verilog <<EOF
+module Module;
+ localparam X;
+endmodule
+EOF
diff --git a/tests/verilog/macro_arg_tromp.sv b/tests/verilog/macro_arg_tromp.sv
new file mode 100644
index 000000000..a9c68a417
--- /dev/null
+++ b/tests/verilog/macro_arg_tromp.sv
@@ -0,0 +1,21 @@
+// Taken from: https://github.com/YosysHQ/yosys/issues/2867
+
+`define MIN(x, y) ((x) < (y) ? (x) : (y))
+`define CEIL_DIV(x, y) (((x) / (y)) + `MIN((x) % (y), 1))
+
+module pad_msg1 (input logic [`MIN(512*`CEIL_DIV(64, 512), 64)-1:0] x,
+ output logic [`MIN(512*`CEIL_DIV(64, 512), 64)-1:0] y);
+ assign y[63:0] = x;
+endmodule
+
+module pad_msg2 (input logic [((512*`CEIL_DIV(64, 512)) < (64) ? (512*`CEIL_DIV(64,512)) : (64))-1:0] x,
+ output logic [((512*`CEIL_DIV(64, 512)) < (64) ? (512*`CEIL_DIV(64,512)) : (64))-1:0] y);
+ assign y[63:0] = x;
+endmodule
+
+module top(...);
+`define add(x) x +
+input [3:0] A;
+output [3:0] B;
+assign B = `add(`add(3)A)A;
+endmodule
diff --git a/tests/verilog/macro_arg_tromp.ys b/tests/verilog/macro_arg_tromp.ys
new file mode 100644
index 000000000..e8bd58e9b
--- /dev/null
+++ b/tests/verilog/macro_arg_tromp.ys
@@ -0,0 +1,2 @@
+logger -expect-no-warnings
+read_verilog -sv macro_arg_tromp.sv
diff --git a/tests/verilog/mem_bounds.sv b/tests/verilog/mem_bounds.sv
new file mode 100644
index 000000000..7fb2fb042
--- /dev/null
+++ b/tests/verilog/mem_bounds.sv
@@ -0,0 +1,27 @@
+module top;
+ reg [0:7] mem [0:2];
+
+ initial mem[1] = '1;
+ wire [31:0] a, b, c, d;
+ assign a = mem[1];
+ assign b = mem[-1];
+ assign c = mem[-1][0];
+ assign d = mem[-1][0:1];
+
+ always @* begin
+
+ assert ($countbits(a, '0) == 24);
+ assert ($countbits(a, '1) == 8);
+ assert ($countbits(a, 'x) == 0);
+
+ assert ($countbits(b, '0) == 24);
+ assert ($countbits(b, 'x) == 8);
+
+ assert ($countbits(c, '0) == 31);
+ assert ($countbits(c, 'x) == 1);
+
+ assert ($countbits(d, '0) == 30);
+ assert ($countbits(d, 'x) == 2);
+
+ end
+endmodule
diff --git a/tests/verilog/mem_bounds.ys b/tests/verilog/mem_bounds.ys
new file mode 100644
index 000000000..42623ad09
--- /dev/null
+++ b/tests/verilog/mem_bounds.ys
@@ -0,0 +1,6 @@
+read_verilog -sv -mem2reg mem_bounds.sv
+proc
+flatten
+opt -full
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all -enable_undef
diff --git a/tests/verilog/module_end_label.ys b/tests/verilog/module_end_label.ys
new file mode 100644
index 000000000..c9e5a13a2
--- /dev/null
+++ b/tests/verilog/module_end_label.ys
@@ -0,0 +1,15 @@
+logger -expect-no-warnings
+read_verilog -sv <<EOF
+module correct_name;
+localparam X = 1;
+endmodule : correct_name
+EOF
+
+design -reset
+
+logger -expect error "Module name \(correct_name\) and end label \(incorrect_name\) don't match\." 1
+read_verilog -sv <<EOF
+module correct_name;
+localparam X = 1;
+endmodule : incorrect_name
+EOF
diff --git a/tests/verilog/net_types.sv b/tests/verilog/net_types.sv
new file mode 100644
index 000000000..7226a7ee5
--- /dev/null
+++ b/tests/verilog/net_types.sv
@@ -0,0 +1,34 @@
+module top;
+ wire logic wire_logic_0; assign wire_logic_0 = 0;
+ wire logic wire_logic_1; assign wire_logic_1 = 1;
+ wand logic wand_logic_0; assign wand_logic_0 = 0; assign wand_logic_0 = 1;
+ wand logic wand_logic_1; assign wand_logic_1 = 1; assign wand_logic_1 = 1;
+ wor logic wor_logic_0; assign wor_logic_0 = 0; assign wor_logic_0 = 0;
+ wor logic wor_logic_1; assign wor_logic_1 = 1; assign wor_logic_1 = 0;
+
+ wire integer wire_integer; assign wire_integer = 4'b1001;
+ wand integer wand_integer; assign wand_integer = 4'b1001; assign wand_integer = 4'b1010;
+ wor integer wor_integer; assign wor_integer = 4'b1001; assign wor_integer = 4'b1010;
+
+ typedef logic [3:0] typename;
+ wire typename wire_typename; assign wire_typename = 4'b1001;
+ wand typename wand_typename; assign wand_typename = 4'b1001; assign wand_typename = 4'b1010;
+ wor typename wor_typename; assign wor_typename = 4'b1001; assign wor_typename = 4'b1010;
+
+ always @* begin
+ assert (wire_logic_0 == 0);
+ assert (wire_logic_1 == 1);
+ assert (wand_logic_0 == 0);
+ assert (wand_logic_1 == 1);
+ assert (wor_logic_0 == 0);
+ assert (wor_logic_1 == 1);
+
+ assert (wire_integer == 4'b1001);
+ assert (wand_integer == 4'b1000);
+ assert (wor_integer == 4'b1011);
+
+ assert (wire_typename == 4'b1001);
+ assert (wand_typename == 4'b1000);
+ assert (wor_typename == 4'b1011);
+ end
+endmodule
diff --git a/tests/verilog/net_types.ys b/tests/verilog/net_types.ys
new file mode 100644
index 000000000..9f75812ea
--- /dev/null
+++ b/tests/verilog/net_types.ys
@@ -0,0 +1,5 @@
+read_verilog -sv net_types.sv
+hierarchy
+proc
+opt -full
+sat -verify -prove-asserts -show-all
diff --git a/tests/verilog/package_end_label.ys b/tests/verilog/package_end_label.ys
new file mode 100644
index 000000000..ccc5c96e9
--- /dev/null
+++ b/tests/verilog/package_end_label.ys
@@ -0,0 +1,15 @@
+logger -expect-no-warnings
+read_verilog -sv <<EOF
+package correct_name;
+localparam X = 1;
+endpackage : correct_name
+EOF
+
+design -reset
+
+logger -expect error "Package name \(correct_name\) and end label \(incorrect_name\) don't match\." 1
+read_verilog -sv <<EOF
+package correct_name;
+localparam X = 1;
+endpackage : incorrect_name
+EOF
diff --git a/tests/verilog/package_task_func.sv b/tests/verilog/package_task_func.sv
new file mode 100644
index 000000000..2df7a5205
--- /dev/null
+++ b/tests/verilog/package_task_func.sv
@@ -0,0 +1,30 @@
+package P;
+ localparam Y = 2;
+ localparam X = Y + 1;
+ task t;
+ output integer x;
+ x = Y;
+ endtask
+ function automatic integer f;
+ input integer i;
+ f = i * X;
+ endfunction
+ function automatic integer g;
+ input integer i;
+ g = i == 0 ? 1 : Y * g(i - 1);
+ endfunction
+ localparam Z = g(4);
+endpackage
+
+module top;
+ integer a;
+ initial P::t(a);
+ integer b = P::f(3);
+ integer c = P::g(3);
+ integer d = P::Z;
+
+ assert property (a == 2);
+ assert property (b == 9);
+ assert property (c == 8);
+ assert property (d == 16);
+endmodule
diff --git a/tests/verilog/package_task_func.ys b/tests/verilog/package_task_func.ys
new file mode 100644
index 000000000..c94cc2acb
--- /dev/null
+++ b/tests/verilog/package_task_func.ys
@@ -0,0 +1,4 @@
+read_verilog -sv package_task_func.sv
+proc
+opt -full
+sat -verify -seq 1 -prove-asserts -show-all
diff --git a/tests/verilog/param_no_default.sv b/tests/verilog/param_no_default.sv
new file mode 100644
index 000000000..cc35bd2ea
--- /dev/null
+++ b/tests/verilog/param_no_default.sv
@@ -0,0 +1,52 @@
+module example #(
+ parameter w,
+ parameter x = 1,
+ parameter byte y,
+ parameter byte z = 3
+) (
+ output a, b,
+ output byte c, d
+);
+ assign a = w;
+ assign b = x;
+ assign c = y;
+ assign d = z;
+endmodule
+
+module top;
+ wire a1, b1;
+ wire a2, b2;
+ wire a3, b3;
+ wire a4, b4;
+ byte c1, d1;
+ byte c2, d2;
+ byte c3, d3;
+ byte c4, d4;
+
+ example #(0, 1, 2) e1(a1, b1, c1, d1);
+ example #(.w(1), .y(4)) e2(a2, b2, c2, d2);
+ example #(.x(0), .w(1), .y(5)) e3(a3, b3, c3, d3);
+ example #(1, 0, 9, 10) e4(a4, b4, c4, d4);
+
+ always @* begin
+ assert (a1 == 0);
+ assert (b1 == 1);
+ assert (c1 == 2);
+ assert (d1 == 3);
+
+ assert (a2 == 1);
+ assert (b2 == 1);
+ assert (c2 == 4);
+ assert (d3 == 3);
+
+ assert (a3 == 1);
+ assert (b3 == 0);
+ assert (c3 == 5);
+ assert (d3 == 3);
+
+ assert (a4 == 1);
+ assert (b4 == 0);
+ assert (c4 == 9);
+ assert (d4 == 10);
+ end
+endmodule
diff --git a/tests/verilog/param_no_default.ys b/tests/verilog/param_no_default.ys
new file mode 100644
index 000000000..7f161a909
--- /dev/null
+++ b/tests/verilog/param_no_default.ys
@@ -0,0 +1,7 @@
+read_verilog -sv param_no_default.sv
+hierarchy
+proc
+flatten
+opt -full
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
diff --git a/tests/verilog/param_no_default_not_svmode.ys b/tests/verilog/param_no_default_not_svmode.ys
new file mode 100644
index 000000000..1ded84e9c
--- /dev/null
+++ b/tests/verilog/param_no_default_not_svmode.ys
@@ -0,0 +1,26 @@
+logger -expect-no-warnings
+read_verilog -sv <<EOF
+module Module;
+ parameter X;
+endmodule
+EOF
+
+design -reset
+
+logger -expect-no-warnings
+read_verilog -sv <<EOF
+module Module #(
+ parameter X
+);
+endmodule
+EOF
+
+design -reset
+
+logger -expect error "Parameter defaults can only be omitted in SystemVerilog mode!" 1
+read_verilog <<EOF
+module Module #(
+ parameter X
+);
+endmodule
+EOF
diff --git a/tests/verilog/param_no_default_unbound_1.ys b/tests/verilog/param_no_default_unbound_1.ys
new file mode 100644
index 000000000..4aab85ab5
--- /dev/null
+++ b/tests/verilog/param_no_default_unbound_1.ys
@@ -0,0 +1,12 @@
+read_verilog -sv <<EOF
+module Example #(
+ parameter X
+);
+endmodule
+module top;
+ Example e();
+endmodule
+EOF
+
+logger -expect error "Parameter `\\X' has no default value and has not been overridden!" 1
+hierarchy -top top
diff --git a/tests/verilog/param_no_default_unbound_2.ys b/tests/verilog/param_no_default_unbound_2.ys
new file mode 100644
index 000000000..4b7f3b028
--- /dev/null
+++ b/tests/verilog/param_no_default_unbound_2.ys
@@ -0,0 +1,12 @@
+read_verilog -sv <<EOF
+module Example #(
+ parameter X, Y
+);
+endmodule
+module top;
+ Example e();
+endmodule
+EOF
+
+logger -expect error "Parameter `\\X' has no default value and has not been overridden!" 1
+hierarchy -top top
diff --git a/tests/verilog/param_no_default_unbound_3.ys b/tests/verilog/param_no_default_unbound_3.ys
new file mode 100644
index 000000000..f32b879a5
--- /dev/null
+++ b/tests/verilog/param_no_default_unbound_3.ys
@@ -0,0 +1,12 @@
+read_verilog -sv <<EOF
+module Example #(
+ parameter X, Y
+);
+endmodule
+module top;
+ Example #(1) e();
+endmodule
+EOF
+
+logger -expect error "Parameter `\\Y' has no default value and has not been overridden!" 1
+hierarchy -top top
diff --git a/tests/verilog/param_no_default_unbound_4.ys b/tests/verilog/param_no_default_unbound_4.ys
new file mode 100644
index 000000000..3a8d69d78
--- /dev/null
+++ b/tests/verilog/param_no_default_unbound_4.ys
@@ -0,0 +1,12 @@
+read_verilog -sv <<EOF
+module Example #(
+ parameter X, Y
+);
+endmodule
+module top;
+ Example #(.Y(1)) e();
+endmodule
+EOF
+
+logger -expect error "Parameter `\\X' has no default value and has not been overridden!" 1
+hierarchy -top top
diff --git a/tests/verilog/param_no_default_unbound_5.ys b/tests/verilog/param_no_default_unbound_5.ys
new file mode 100644
index 000000000..30282eba7
--- /dev/null
+++ b/tests/verilog/param_no_default_unbound_5.ys
@@ -0,0 +1,12 @@
+read_verilog -sv <<EOF
+module Example #(
+ parameter X, Y = 2
+);
+endmodule
+module top;
+ Example #(.Y(1)) e();
+endmodule
+EOF
+
+logger -expect error "Parameter `\\X' has no default value and has not been overridden!" 1
+hierarchy -top top
diff --git a/tests/verilog/parameters_across_files.ys b/tests/verilog/parameters_across_files.ys
new file mode 100644
index 000000000..c53e40179
--- /dev/null
+++ b/tests/verilog/parameters_across_files.ys
@@ -0,0 +1,20 @@
+read_verilog -sv <<EOF
+parameter Q = 1;
+EOF
+read_verilog -sv <<EOF
+parameter P = Q;
+module top(
+ output integer out
+);
+ assign out = P;
+ always @*
+ assert (out == 1);
+endmodule
+EOF
+
+hierarchy
+proc
+flatten
+opt -full
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
diff --git a/tests/verilog/prefix.sv b/tests/verilog/prefix.sv
new file mode 100644
index 000000000..2d7fbb134
--- /dev/null
+++ b/tests/verilog/prefix.sv
@@ -0,0 +1,95 @@
+module top;
+ genvar i, j;
+ if (1) begin : blk1
+ integer a = 1;
+ for (i = 0; i < 2; i = i + 1) begin : blk2
+ integer b = i;
+ for (j = 0; j < 2; j = j + 1) begin : blk3
+ integer c = j;
+ localparam x = i;
+ localparam y = j;
+ always @* begin
+ assert (1 == a);
+ assert (1 == blk1.a);
+ assert (1 == top.blk1.a);
+ assert (i == b);
+ assert (i == blk2[i].b);
+ assert (i == blk1.blk2[i].b);
+ assert (i == top.blk1.blk2[i].b);
+ assert (i == blk2[x].b);
+ assert (i == blk1.blk2[x].b);
+ assert (i == top.blk1.blk2[x].b);
+ assert (j == c);
+ assert (j == blk3[j].c);
+ assert (j == blk2[x].blk3[j].c);
+ assert (j == blk1.blk2[x].blk3[j].c);
+ assert (j == top.blk1.blk2[x].blk3[j].c);
+ assert (j == c);
+ assert (j == blk3[y].c);
+ assert (j == blk2[x].blk3[y].c);
+ assert (j == blk1.blk2[x].blk3[y].c);
+ assert (j == top.blk1.blk2[x].blk3[y].c);
+ assert (j == top.blk1.blk2[x].blk3[y].c[0]);
+ assert (0 == top.blk1.blk2[x].blk3[y].c[1]);
+ assert (0 == top.blk1.blk2[x].blk3[y].c[j]);
+ end
+ end
+ always @* begin
+ assert (1 == a);
+ assert (1 == blk1.a);
+ assert (1 == top.blk1.a);
+ assert (i == b);
+ assert (i == blk2[i].b);
+ assert (i == blk1.blk2[i].b);
+ assert (i == top.blk1.blk2[i].b);
+ assert (0 == blk3[0].c);
+ assert (0 == blk2[i].blk3[0].c);
+ assert (0 == blk1.blk2[i].blk3[0].c);
+ assert (0 == top.blk1.blk2[i].blk3[0].c);
+ assert (1 == blk3[1].c);
+ assert (1 == blk2[i].blk3[1].c);
+ assert (1 == blk1.blk2[i].blk3[1].c);
+ assert (1 == top.blk1.blk2[i].blk3[1].c);
+ end
+ end
+ always @* begin
+ assert (1 == a);
+ assert (1 == blk1.a);
+ assert (1 == top.blk1.a);
+ assert (0 == blk2[0].b);
+ assert (0 == blk1.blk2[0].b);
+ assert (0 == top.blk1.blk2[0].b);
+ assert (1 == blk2[1].b);
+ assert (1 == blk1.blk2[1].b);
+ assert (1 == top.blk1.blk2[1].b);
+ assert (0 == blk2[0].blk3[0].c);
+ assert (0 == blk1.blk2[0].blk3[0].c);
+ assert (0 == top.blk1.blk2[0].blk3[0].c);
+ assert (1 == blk2[0].blk3[1].c);
+ assert (1 == blk1.blk2[0].blk3[1].c);
+ assert (1 == top.blk1.blk2[0].blk3[1].c);
+ assert (0 == blk2[1].blk3[0].c);
+ assert (0 == blk1.blk2[1].blk3[0].c);
+ assert (0 == top.blk1.blk2[1].blk3[0].c);
+ assert (1 == blk2[1].blk3[1].c);
+ assert (1 == blk1.blk2[1].blk3[1].c);
+ assert (1 == top.blk1.blk2[1].blk3[1].c);
+ end
+ end
+ always @* begin
+ assert (1 == blk1.a);
+ assert (1 == top.blk1.a);
+ assert (0 == blk1.blk2[0].b);
+ assert (0 == top.blk1.blk2[0].b);
+ assert (1 == blk1.blk2[1].b);
+ assert (1 == top.blk1.blk2[1].b);
+ assert (0 == blk1.blk2[0].blk3[0].c);
+ assert (0 == top.blk1.blk2[0].blk3[0].c);
+ assert (1 == blk1.blk2[0].blk3[1].c);
+ assert (1 == top.blk1.blk2[0].blk3[1].c);
+ assert (0 == blk1.blk2[1].blk3[0].c);
+ assert (0 == top.blk1.blk2[1].blk3[0].c);
+ assert (1 == blk1.blk2[1].blk3[1].c);
+ assert (1 == top.blk1.blk2[1].blk3[1].c);
+ end
+endmodule
diff --git a/tests/verilog/prefix.ys b/tests/verilog/prefix.ys
new file mode 100644
index 000000000..ed3b3a111
--- /dev/null
+++ b/tests/verilog/prefix.ys
@@ -0,0 +1,5 @@
+read_verilog -sv prefix.sv
+hierarchy
+proc
+select -module top
+sat -verify -seq 1 -prove-asserts -show-all
diff --git a/tests/verilog/size_cast.sv b/tests/verilog/size_cast.sv
new file mode 100644
index 000000000..1636f8d70
--- /dev/null
+++ b/tests/verilog/size_cast.sv
@@ -0,0 +1,140 @@
+module top;
+ logic L1b0 = 0;
+ logic L1b1 = 1;
+
+ logic signed L1sb0 = 0;
+ logic signed L1sb1 = 1;
+
+ logic [1:0] L2b00 = 0;
+ logic [1:0] L2b01 = 1;
+ logic [1:0] L2b10 = 2;
+ logic [1:0] L2b11 = 3;
+
+ logic signed [1:0] L2sb00 = 0;
+ logic signed [1:0] L2sb01 = 1;
+ logic signed [1:0] L2sb10 = 2;
+ logic signed [1:0] L2sb11 = 3;
+
+ logic y = 1;
+
+ always @* begin
+
+ assert (1'(L1b0 ) == 1'b0);
+ assert (1'(L1b1 ) == 1'b1);
+ assert (1'(L1sb0 ) == 1'b0);
+ assert (1'(L1sb1 ) == 1'b1);
+ assert (1'(L2b00 ) == 1'b0);
+ assert (1'(L2b01 ) == 1'b1);
+ assert (1'(L2b10 ) == 1'b0);
+ assert (1'(L2b11 ) == 1'b1);
+ assert (1'(L2sb00) == 1'b0);
+ assert (1'(L2sb01) == 1'b1);
+ assert (1'(L2sb10) == 1'b0);
+ assert (1'(L2sb11) == 1'b1);
+
+ assert (2'(L1b0 ) == 2'b00);
+ assert (2'(L1b1 ) == 2'b01);
+ assert (2'(L1sb0 ) == 2'b00);
+ assert (2'(L1sb1 ) == 2'b11);
+ assert (2'(L2b00 ) == 2'b00);
+ assert (2'(L2b01 ) == 2'b01);
+ assert (2'(L2b10 ) == 2'b10);
+ assert (2'(L2b11 ) == 2'b11);
+ assert (2'(L2sb00) == 2'b00);
+ assert (2'(L2sb01) == 2'b01);
+ assert (2'(L2sb10) == 2'b10);
+ assert (2'(L2sb11) == 2'b11);
+
+ assert (3'(L1b0 ) == 3'b000);
+ assert (3'(L1b1 ) == 3'b001);
+ assert (3'(L1sb0 ) == 3'b000);
+ assert (3'(L1sb1 ) == 3'b111);
+ assert (3'(L2b00 ) == 3'b000);
+ assert (3'(L2b01 ) == 3'b001);
+ assert (3'(L2b10 ) == 3'b010);
+ assert (3'(L2b11 ) == 3'b011);
+ assert (3'(L2sb00) == 3'b000);
+ assert (3'(L2sb01) == 3'b001);
+ assert (3'(L2sb10) == 3'b110);
+ assert (3'(L2sb11) == 3'b111);
+
+ assert (3'(L1b0 | '1) == 3'b111);
+ assert (3'(L1b1 | '1) == 3'b111);
+ assert (3'(L1sb0 | '1) == 3'b111);
+ assert (3'(L1sb1 | '1) == 3'b111);
+ assert (3'(L2b00 | '1) == 3'b111);
+ assert (3'(L2b01 | '1) == 3'b111);
+ assert (3'(L2b10 | '1) == 3'b111);
+ assert (3'(L2b11 | '1) == 3'b111);
+ assert (3'(L2sb00 | '1) == 3'b111);
+ assert (3'(L2sb01 | '1) == 3'b111);
+ assert (3'(L2sb10 | '1) == 3'b111);
+ assert (3'(L2sb11 | '1) == 3'b111);
+
+ assert (3'(L1b0 | '0) == 3'b000);
+ assert (3'(L1b1 | '0) == 3'b001);
+ assert (3'(L1sb0 | '0) == 3'b000);
+ assert (3'(L1sb1 | '0) == 3'b001);
+ assert (3'(L2b00 | '0) == 3'b000);
+ assert (3'(L2b01 | '0) == 3'b001);
+ assert (3'(L2b10 | '0) == 3'b010);
+ assert (3'(L2b11 | '0) == 3'b011);
+ assert (3'(L2sb00 | '0) == 3'b000);
+ assert (3'(L2sb01 | '0) == 3'b001);
+ assert (3'(L2sb10 | '0) == 3'b010);
+ assert (3'(L2sb11 | '0) == 3'b011);
+
+ assert (3'(y ? L1b0 : '1) == 3'b000);
+ assert (3'(y ? L1b1 : '1) == 3'b001);
+ assert (3'(y ? L1sb0 : '1) == 3'b000);
+ assert (3'(y ? L1sb1 : '1) == 3'b001);
+ assert (3'(y ? L2b00 : '1) == 3'b000);
+ assert (3'(y ? L2b01 : '1) == 3'b001);
+ assert (3'(y ? L2b10 : '1) == 3'b010);
+ assert (3'(y ? L2b11 : '1) == 3'b011);
+ assert (3'(y ? L2sb00 : '1) == 3'b000);
+ assert (3'(y ? L2sb01 : '1) == 3'b001);
+ assert (3'(y ? L2sb10 : '1) == 3'b010);
+ assert (3'(y ? L2sb11 : '1) == 3'b011);
+
+ assert (3'(y ? L1b0 : '0) == 3'b000);
+ assert (3'(y ? L1b1 : '0) == 3'b001);
+ assert (3'(y ? L1sb0 : '0) == 3'b000);
+ assert (3'(y ? L1sb1 : '0) == 3'b001);
+ assert (3'(y ? L2b00 : '0) == 3'b000);
+ assert (3'(y ? L2b01 : '0) == 3'b001);
+ assert (3'(y ? L2b10 : '0) == 3'b010);
+ assert (3'(y ? L2b11 : '0) == 3'b011);
+ assert (3'(y ? L2sb00 : '0) == 3'b000);
+ assert (3'(y ? L2sb01 : '0) == 3'b001);
+ assert (3'(y ? L2sb10 : '0) == 3'b010);
+ assert (3'(y ? L2sb11 : '0) == 3'b011);
+
+ assert (3'(y ? L1b0 : 1'sb0) == 3'b000);
+ assert (3'(y ? L1b1 : 1'sb0) == 3'b001);
+ assert (3'(y ? L1sb0 : 1'sb0) == 3'b000);
+ assert (3'(y ? L1sb1 : 1'sb0) == 3'b111);
+ assert (3'(y ? L2b00 : 1'sb0) == 3'b000);
+ assert (3'(y ? L2b01 : 1'sb0) == 3'b001);
+ assert (3'(y ? L2b10 : 1'sb0) == 3'b010);
+ assert (3'(y ? L2b11 : 1'sb0) == 3'b011);
+ assert (3'(y ? L2sb00 : 1'sb0) == 3'b000);
+ assert (3'(y ? L2sb01 : 1'sb0) == 3'b001);
+ assert (3'(y ? L2sb10 : 1'sb0) == 3'b110);
+ assert (3'(y ? L2sb11 : 1'sb0) == 3'b111);
+
+ assert (3'(y ? L1b0 : 1'sb1) == 3'b000);
+ assert (3'(y ? L1b1 : 1'sb1) == 3'b001);
+ assert (3'(y ? L1sb0 : 1'sb1) == 3'b000);
+ assert (3'(y ? L1sb1 : 1'sb1) == 3'b111);
+ assert (3'(y ? L2b00 : 1'sb1) == 3'b000);
+ assert (3'(y ? L2b01 : 1'sb1) == 3'b001);
+ assert (3'(y ? L2b10 : 1'sb1) == 3'b010);
+ assert (3'(y ? L2b11 : 1'sb1) == 3'b011);
+ assert (3'(y ? L2sb00 : 1'sb1) == 3'b000);
+ assert (3'(y ? L2sb01 : 1'sb1) == 3'b001);
+ assert (3'(y ? L2sb10 : 1'sb1) == 3'b110);
+ assert (3'(y ? L2sb11 : 1'sb1) == 3'b111);
+
+ end
+endmodule
diff --git a/tests/verilog/size_cast.ys b/tests/verilog/size_cast.ys
new file mode 100644
index 000000000..6890cd2d5
--- /dev/null
+++ b/tests/verilog/size_cast.ys
@@ -0,0 +1,5 @@
+read_verilog -sv size_cast.sv
+proc
+opt -full
+select -module top
+sat -verify -prove-asserts -show-all
diff --git a/tests/verilog/struct_access.sv b/tests/verilog/struct_access.sv
new file mode 100644
index 000000000..f13b8dd51
--- /dev/null
+++ b/tests/verilog/struct_access.sv
@@ -0,0 +1,88 @@
+module top;
+
+ typedef struct packed {
+ logic a;
+ logic signed b;
+ byte c;
+ byte unsigned d;
+ reg [3:0] e;
+ reg signed [3:0] f;
+ struct packed {
+ logic a;
+ logic signed b;
+ } x;
+ struct packed signed {
+ logic a;
+ logic signed b;
+ } y;
+ } S;
+ S s;
+
+ initial begin
+ // test codegen for LHS
+ s.a = '1;
+ s.b = '1;
+ s.c = '1;
+ s.d = '1;
+ s.e = '1;
+ s.f = '1;
+ s.x.a = '1;
+ s.x.b = '1;
+ s.y.a = '1;
+ s.y.b = '1;
+ end
+
+`define CHECK(expr, width, signedness) \
+ case (expr) \
+ 1'sb1: \
+ case (expr) \
+ 2'sb11: if (!(signedness)) fail = 1; \
+ default: if (signedness) fail = 1; \
+ endcase \
+ default: if (signedness) fail = 1; \
+ endcase \
+ case (expr) \
+ 1'b1: if ((width) != 1) fail = 1; \
+ 2'b11: if ((width) != 2) fail = 1; \
+ 3'b111: if ((width) != 3) fail = 1; \
+ 4'b1111: if ((width) != 4) fail = 1; \
+ 5'b1111_1: if ((width) != 5) fail = 1; \
+ 6'b1111_11: if ((width) != 6) fail = 1; \
+ 7'b1111_11: if ((width) != 7) fail = 1; \
+ 8'b1111_1111: if ((width) != 8) fail = 1; \
+ 9'b1111_1111_1: if ((width) != 9) fail = 1; \
+ default: fail = 1; \
+ endcase \
+ begin \
+ reg [9:0] indirect; \
+ indirect = (expr); \
+ if ((indirect != (expr)) != (signedness)) fail = 1; \
+ indirect = $unsigned(expr); \
+ if ($countones(indirect) != (width)) fail = 1; \
+ end
+
+ initial begin
+ reg fail;
+ fail = 0;
+
+ `CHECK(s.a, 1, 0)
+ `CHECK(s.b, 1, 1)
+ `CHECK(s.c, 8, 1)
+ `CHECK(s.d, 8, 0)
+ `CHECK(s.e, 4, 0)
+ `CHECK(s.f, 4, 1)
+
+ `CHECK(s.x.a, 1, 0)
+ `CHECK(s.x.b, 1, 1)
+ `CHECK(s.y.a, 1, 0)
+ `CHECK(s.y.b, 1, 1)
+
+ // TODO(zachjs): support access to whole sub-structs and unions
+ // `CHECK(s.x, 2, 0)
+ // `CHECK(s.y, 2, 1)
+
+ assert (fail === 0);
+ end
+
+
+endmodule
diff --git a/tests/verilog/struct_access.ys b/tests/verilog/struct_access.ys
new file mode 100644
index 000000000..29d569c01
--- /dev/null
+++ b/tests/verilog/struct_access.ys
@@ -0,0 +1,4 @@
+read_verilog -formal -sv struct_access.sv
+proc
+opt -full
+sat -verify -seq 1 -prove-asserts -show-all
diff --git a/tests/verilog/typedef_across_files.ys b/tests/verilog/typedef_across_files.ys
new file mode 100644
index 000000000..ca9bba736
--- /dev/null
+++ b/tests/verilog/typedef_across_files.ys
@@ -0,0 +1,23 @@
+read_verilog -sv <<EOF
+typedef logic T;
+EOF
+
+read_verilog -sv <<EOF
+typedef T [3:0] S;
+EOF
+
+read_verilog -sv <<EOF
+module top;
+ T t;
+ S s;
+ always @* begin
+ assert ($bits(t) == 1);
+ assert ($bits(s) == 4);
+ end
+endmodule
+EOF
+
+proc
+opt -full
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
diff --git a/tests/verilog/typedef_legacy_conflict.ys b/tests/verilog/typedef_legacy_conflict.ys
new file mode 100644
index 000000000..8dff4ec5f
--- /dev/null
+++ b/tests/verilog/typedef_legacy_conflict.ys
@@ -0,0 +1,37 @@
+read_verilog -sv <<EOF
+typedef logic T;
+typedef T [3:0] S;
+EOF
+
+read_verilog -sv <<EOF
+module example;
+ // S and T refer to the definitions from the first file
+ T t;
+ S s;
+ always @* begin
+ assert ($bits(t) == 1);
+ assert ($bits(s) == 4);
+ end
+endmodule
+
+typedef byte T;
+typedef T S;
+
+module top;
+ // S and T refer to the most recent overrides
+ T t;
+ S s;
+ always @* begin
+ assert ($bits(t) == 8);
+ assert ($bits(s) == 8);
+ end
+ example e();
+endmodule
+EOF
+
+hierarchy
+proc
+flatten
+opt -full
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
diff --git a/tests/verilog/unbased_unsized.sv b/tests/verilog/unbased_unsized.sv
new file mode 100644
index 000000000..1d0c5a72c
--- /dev/null
+++ b/tests/verilog/unbased_unsized.sv
@@ -0,0 +1,40 @@
+module pass_through(
+ input [63:0] inp,
+ output [63:0] out
+);
+ assign out = inp;
+endmodule
+
+module top;
+ logic [63:0]
+ o01, o02, o03, o04,
+ o05, o06, o07, o08,
+ o09, o10, o11, o12,
+ o13, o14, o15, o16;
+ assign o01 = '0;
+ assign o02 = '1;
+ assign o03 = 'x;
+ assign o04 = 'z;
+ assign o05 = 3'('0);
+ assign o06 = 3'('1);
+ assign o07 = 3'('x);
+ assign o08 = 3'('z);
+ pass_through pt09('0, o09);
+ pass_through pt10('1, o10);
+ pass_through pt11('x, o11);
+ pass_through pt12('z, o12);
+ always @* begin
+ assert (o01 === {64 {1'b0}});
+ assert (o02 === {64 {1'b1}});
+ assert (o03 === {64 {1'bx}});
+ assert (o04 === {64 {1'bz}});
+ assert (o05 === {61'b0, 3'b000});
+ assert (o06 === {61'b0, 3'b111});
+ assert (o07 === {61'b0, 3'bxxx});
+ assert (o08 === {61'b0, 3'bzzz});
+ assert (o09 === {64 {1'b0}});
+ assert (o10 === {64 {1'b1}});
+ assert (o11 === {64 {1'bx}});
+ assert (o12 === {64 {1'bz}});
+ end
+endmodule
diff --git a/tests/verilog/unbased_unsized.ys b/tests/verilog/unbased_unsized.ys
new file mode 100644
index 000000000..e1bc99c64
--- /dev/null
+++ b/tests/verilog/unbased_unsized.ys
@@ -0,0 +1,7 @@
+read_verilog -sv unbased_unsized.sv
+hierarchy
+proc
+flatten
+opt -full
+select -module top
+sat -verify -seq 1 -tempinduct -prove-asserts -show-all
diff --git a/tests/verilog/unbased_unsized_tern.sv b/tests/verilog/unbased_unsized_tern.sv
new file mode 100644
index 000000000..ad8493394
--- /dev/null
+++ b/tests/verilog/unbased_unsized_tern.sv
@@ -0,0 +1,31 @@
+module pass_through #(
+ parameter WIDTH = 1
+) (
+ input logic [WIDTH-1:0] inp,
+ output logic [WIDTH-1:0] out
+);
+ assign out = inp;
+endmodule
+
+module gate (
+ input logic inp,
+ output logic [63:0]
+ out1, out2, out3, out4
+);
+ pass_through #(40) pt1('1, out1);
+ pass_through #(40) pt2(inp ? '1 : '0, out2);
+ pass_through #(40) pt3(inp ? '1 : 2'b10, out3);
+ pass_through #(40) pt4(inp ? '1 : inp, out4);
+endmodule
+
+module gold (
+ input logic inp,
+ output logic [63:0]
+ out1, out2, out3, out4
+);
+ localparam ONES = 40'hFF_FFFF_FFFF;
+ pass_through #(40) pt1(ONES, out1);
+ pass_through #(40) pt2(inp ? ONES : 0, out2);
+ pass_through #(40) pt3(inp ? ONES : 2'sb10, out3);
+ pass_through #(40) pt4(inp ? ONES : inp, out4);
+endmodule
diff --git a/tests/verilog/unbased_unsized_tern.ys b/tests/verilog/unbased_unsized_tern.ys
new file mode 100644
index 000000000..5ef63c559
--- /dev/null
+++ b/tests/verilog/unbased_unsized_tern.ys
@@ -0,0 +1,6 @@
+read_verilog -sv unbased_unsized_tern.sv
+hierarchy
+proc
+equiv_make gold gate equiv
+equiv_simple
+equiv_status -assert
diff --git a/tests/verilog/unmatched_endif_2.ys b/tests/verilog/unmatched_endif_2.ys
new file mode 100644
index 000000000..2ee084170
--- /dev/null
+++ b/tests/verilog/unmatched_endif_2.ys
@@ -0,0 +1,7 @@
+logger -expect error "Found `endif outside of macro conditional branch!" 1
+read_verilog <<EOF
+`ifndef a
+`else
+`endif
+`endif
+EOF
diff --git a/tests/vloghtb/run-test.sh b/tests/vloghtb/run-test.sh
index ad99226e7..3c0689619 100755
--- a/tests/vloghtb/run-test.sh
+++ b/tests/vloghtb/run-test.sh
@@ -3,7 +3,7 @@
set -ex
rm -rf Makefile refdat rtl scripts spec
-wget -N http://www.clifford.at/yosys/nogit/vloghammer_tb.tar.bz2
+wget -N https://yosyshq.net/yosys/nogit/vloghammer_tb.tar.bz2
tar --strip=1 -xjf vloghammer_tb.tar.bz2
make clean